by Thomas Letan & Chris Pinnock

This article first appeared at Tezos Commons on March 10th 2023. The original article was written when the Mumbainet protocol was being evaluated. We are keeping the article up to date here. Last update 23/2/2024.


A rollup is a means of processing transactions away from the main blockchain, “rolling them up” and injecting them back later. Tezos’s upgrade Mumbai introduced the smart rollup feature to mainnet. A smart rollup is a rollup managed by a WebAssembly (Wasm) program, and can be used to implement a wide variety of use cases.

Applications include:

  • Enhanced performance and increased throughput by allowing organisations to manage their transactions in a rollup;
  • Running code off-chain to reduce load on the primary blockchain;
  • Providing a virtual machine environment compatible with other blockchain smart contract languages (such as Ethereum’s), thus providing a migration path for developers from other blockchains.

This short article will show you how get started with a rollup on the Ghostnet test network. It will also work on mainnet. Please be careful - any Tezos wallet you manage on mainnet should be well-protected. We do not delve into the technical detail. For further reading, please refer to the Smart Rollup Developer Documentation. We assume the following prerequisites:

  • A working Debian or Ubuntu Linux machine running a rolling Tezos Node with Octez v17.0 or later.
  • To run a smart rollup daemon, you will need to reserve at least 10,000ꜩ which will be frozen as a security deposit. Additionally, some funds should be reserved to pay the fees of the Layer 1 operations.

Let’s start by setting these up including setting a wallet up on the Nariobi net.

1 - Setting up the node

You can setup the Octez software by building from source. Alternatively, you can use an article by one of the authors to setup a node. For smart rollups, you will need to use the v19.1 packages at the download site.

The article suggests using a dedicated user tezos for running the software and we assume the same in this article. Make sure that you setup the node for Ghostnet and use a Ghostnet snapshot. For example, when you configure the node use:

sudo su - tezos
octez-node config init --data-dir /var/tezos/node \
	--network ghostnet \
	--history-mode=rolling \
	--net-addr="[::]:9732" \

Then as root install the Smart Rollup daemons, installing any dependencies identified. For example, on Ubuntu Linux:

dpkg -i ./octez-smartrollup_19.1-1_amd64.deb

2 - Setting up the wallet

You can setup a wallet on the machine and obtain 10,000 test ꜩ as follows. This procedure is not recommended on mainnet where you should protect your keys. We are assuming that you are running on a test network. Firstly, create a wallet which will be aliased as operator.

sudo su - tezos
octez-client gen keys operator
octez-client list known addresses

Use the Tezos address in the output of the last command. In our case it is tz1gUp6L56GvuLVk3ZFoFZ6bqckFZf6XgYsm (see below).

operator: tz1gUp6L56GvuLVk3ZFoFZ6bqckFZf6XgYsm (unencrypted sk known)

Obtain 10,000ꜩ from the Ghostnet faucet. You will need request two sets of tokens as the maximum request is 6,001ꜩ. The resulting 12,002ꜩ will be enough for the deposit and the Layer 1 fees.

$ octez-client get balance for operator
12002 ꜩ

3 - Choosing a WASM Kernel

For this article, we will use an experimental kernel provided by the Octez development team. This kernel is a simple “echo kernel” which sends back any transactions it receives to the Layer 1 chain. The Smart Rollup Developer Documentation uses it to demonstrate the various interactions users can have with a smart rollup. Download the shell script which contains it.

echo ${KERNEL}

The KERNEL environment variable now contains the encoded Wasm kernel. If you use tcsh or csh you will need to adjust the script accordingly as it sets an environment variable.

4 - Creating the Rollup and configuring the Rollup Daemons

Assuming that the local wallet is called operator, initiate the rollup using the octez-client command (as tezos):

octez-client originate smart rollup sr_alias from operator \
    of kind wasm_2_0_0 \
    of type bytes \
    with kernel "${KERNEL}" \
    --burn-cap 999

The smart rollup node can be configured to provide a certain number of services, and can be configured to use more than one address. You can refer to the developer documentation for more information.

The --burn-cap option limits the amount of ꜩ burned during the operation. You should adjust the amount to one acceptable for you (particularly if you are on mainnet).

Provided that the origination is successful, there will be a line in the output containing the smart rollup address. The address begins with sr1 and in our example output below it is sr16sXnn7syKanQyVdXJ2h1VxKxmSE52NNsv.

Estimated gas: 2748.229 units (will add 100 for safety)
Estimated storage: 6552 bytes added (will add 20 for safety)
Operation successfully injected in the node.
Operation hash is 'ooU5aURNgPGcvuHrSxtWJ61NoBMdD5H6nh8smStGV8JhE1ip8Ac'
Waiting for the operation to be included...
Operation found in block: BMA1mBzZZfra2cAhYVUQ5G2d7qWNrr62UGzE4PnM4rMhr2v5SYm (pass: 3, offset: 0)
This sequence of operations was run:
  Manager signed operations:
    From: tz1gUp6L56GvuLVk3ZFoFZ6bqckFZf6XgYsm
    Fee to the baker: ꜩ0.001054
    Expected counter: 285427
    Gas limit: 2849
    Storage limit: 6572 bytes
    Balance updates:
      tz1gUp6L56GvuLVk3ZFoFZ6bqckFZf6XgYsm ... -ꜩ0.001054
      payload fees(the block proposer) ....... +ꜩ0.001054
    Smart rollup origination:
      Kind: wasm_2_0_0
      Parameter type: bytes
      Kernel Blake2B hash: '24df9e3c520dd9a9c49b447766e8a604d31138c1aacb4a67532499c6a8b348cc'
      This smart rollup origination was successfully applied
      Consumed gas: 2748.269
      Storage size: 6552 bytes
      Address: sr16sXnn7syKanQyVdXJ2h1VxKxmSE52NNsv
      Genesis commitment hash: src148CUpWBSWdiACxJU7qmM83EPSwJUnGXvT3UoR1wMskb7qDn9o8
      Balance updates:
        tz1gUp6L56GvuLVk3ZFoFZ6bqckFZf6XgYsm ... -ꜩ1.638
        storage fees ........................... +ꜩ1.638

The operation has only been included 0 blocks ago.
We recommend to wait more.
Use command
  octez-client wait for ooU5aURNgPGcvuHrSxtWJ61NoBMdD5H6nh8smStGV8JhE1ip8Ac to be included --confirmations 1 --branch BLkRNr2dgMbmpxvmmohneG4Q6zAGv6AperavsgdDJzYzTfuHrYJ
and/or an external block explorer.

From the perspective of the Layer 1, the only power the operator wallet has over the originated smart rollup is to choose its program. Afterwards, the life cycle of the smart rollup can be handled by any implicit account, as long as they agree to lock 10,000ꜩ.

Create a working directory. Then use the smart rollup address and the wallet address to configure the rollup daemons using the currently active protocol as follows:

mkdir -p /var/tezos/smartrollup
octez-smart-rollup-node init operator config for sr_alias \
    with operators operator \
    --data-dir "/var/tezos/smartrollup"

5 - Running the Rollup Daemons

If you are using the packages mentioned above, you can run the smart rollup daemons using systemctl as root. They can be setup to start at boot time. Check that /etc/octez/smartrollup.conf is suitable for your environment before running.

systemctl enable octez-smartrollup
systemctl start octez-smartrollup

Alternatively, you can run the rollup daemon by hand (as tezos) and see the logs on the terminal:

octez-smart-rollup-node run --data-dir /var/tezos/smartrollup

Finally, to test the rollup you can inject a simple message into it. We breakdown the example given on the development site. The detail is beyond the scope of this article. Firstly originate a contract on the blockchain as follows:

sudo su - tezos
octez-client originate contract testcontract transferring 1 from operator \
    running 'parameter string; storage string; code {CAR; NIL operation; PAIR};' \
    --init '""' --burn-cap 0.4

This will return a contract identifier like this one:

New contract KT1ABda79D6zcmRvKPoTYsqddDhrhWCqjCzr originated.

Using the tezos account, encode a simple message using the smart rollup client (the MESSAGE declaration is one line):

MESSAGE='[ { "destination" : "KT1ABda79D6zcmRvKPoTYsqddDhrhWCqjCzr",
		"parameters" : "\"Hello Tezos Commons\"",
		"entrypoint" : "%default" } ]'

EMESSAGE=`octez-smart-rollup-client encode outbox message "$MESSAGE"`

Send the message to the rollup using the octez-client command.

octez-client send smart rollup message "hex:[ \"${EMESSAGE}\" ]" from operator

You have now seen how to setup a rollup and submit messages to it. There is obviously a lot more detail happening under the hood than we can give here. You can view the transactions on the blockchain by downloading the relevant blocks from the node, for example:

wget http://YOURNODE:8732/chains/main/blocks/BLOCK_ID

In a similar transaction to above, here are the sections of the blocks downloaded and formatted using jq. This block shows that the smart rollup node has published a commitment that is an update of the rollup state.

        "protocol": "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK",
        "chain_id": "NetXzfS4qFhir8c",
        "hash": "onjf4VukkZ2BYkhbnjtKMia35xzTkQwoYctrYZ8sNwBh2BRgDSq",
        "branch": "BMDnbi8TKyDbNR4144Um15jCoLGEh2WejS5j2iM68SPTVcRqZZc",
        "contents": [
            "kind": "smart_rollup_publish",
            "source": "tz1gUp6L56GvuLVk3ZFoFZ6bqckFZf6XgYsm",
            "fee": "963",
            "counter": "3941",
            "gas_limit": "6418",
            "storage_limit": "0",
            "rollup": "sr1Hp6fvRDkKUsFsdLXoFiAn1tVCjkpmSygb",
            "commitment": {
              "compressed_state": "srs12QdRrhCEj8N8HjbsZNQVd8x4EVzfT9SBCfzNSHqS97i6yWVXA9",
              "inbox_level": 8958,
              "predecessor": "src13eN6KaiGH66HDYRsoXdZBiQ1GT24qjDusgCuEkrEiL2MUxEGA3",
              "number_of_ticks": "880000000000"
            "metadata": {
              "balance_updates": [
                  "kind": "contract",
                  "contract": "tz1gUp6L56GvuLVk3ZFoFZ6bqckFZf6XgYsm",
                  "change": "-963",
                  "origin": "block"
                  "kind": "accumulator",
                  "category": "block fees",
                  "change": "963",
                  "origin": "block"
              "operation_result": {
                "status": "applied",
                "consumed_milligas": "6317837",
                "staked_hash": "src12cod31ux6yxPBEhhWSX7nW3bodNRxdMHnzMjLNYVRfLCG3dXNp",
                "published_at_level": 8961,
                "balance_updates": []

Smart rollups are optimistic rollups. This means that when a smart rollup node publishes a state update with a commitment, the Layer 1 does not have any means to know whether or not this commitment is correct or not. However it features a permissionless dispute mechanism to allow an honest participant to refute malicious commitments. This mechanism is already supported by the smart rollup node, which can automatically start and carry out disputes. However, it is out of scope of this article.

Note that this last example was undertaken on Weeklynet instead of Ghostnet. You can also use Weeklynet for your smart rollup testing but you will need to use the right development version of Octez to match the network.


Thanks to John Newby for some useful discussions during the preparation of this paper.