Flextesa: EVM Smart-Rollup Sandbox

Phillip Saxton
The Aleph
Published in
8 min readJan 26, 2024

The addition of Smart Optimistic Rollups on Tezos brings the possibility of interoperability with applications, developed for different blockchains. The Etherlink project, developed by Nomadic Labs, brings this to reality by enabling EVM (Ethereum Virtual Machine) base applications to operate on the Tezos network within a smart optimistic rollup.

In an effort to assist developers with building and testing of EVM Rollup based applications, Flextesa now includes the EVM Rollup Sandbox. This article will demonstrate running the sandbox and its interoperability with EVM based tools — MetaMask and Remix. To learn more about the Etherlink see its documentation.

Michelson-Morley experiment

Starting the Sandbox

For this demonstration we will run Flextesa in a Docker container with the image bedlow. It’s built from the “dev” branch of Flextesta repository.

image='registry.gitlab.com/tezos/flextesa:3b8b6595-run'

To launch the EVM Rollup Sandbox, use the following Docker command:

docker run --rm --detach -p 20004:20004 --name my-sandbox \
"$image" oxfordbox start_evm_smart_rollup

This will start the Flextesa mini-network, which is a single node sandbox with a baker advancing the blockchain. After a short wait the EVM Rollup will be originated. Next the octez-smart-rollup-node and octez-evm-node will start. You can check that smart-rollup is available and see their configurations with the following command:

docker exec my-sandbox oxfordbox smart_rollup_info

If the output is empty, wait a few moments and try the command again. When the EVM Rollup is ready, you will see something like this:

{
"smart_rollup_node_config": {
"smart-rollup-address": "sr1Gn2mUQvPENyM3eu5L4EYZHHDWvHCEW59C",
"smart-rollup-node-operator": {
"operating": "tz1XeHf9iK1gy3tEY52uCbJaN8VAHwqpYA4S",
"batching": [
"tz1XeHf9iK1gy3tEY52uCbJaN8VAHwqpYA4S"
],
"cementing": "tz1XeHf9iK1gy3tEY52uCbJaN8VAHwqpYA4S",
"executing_outbox": "tz1XeHf9iK1gy3tEY52uCbJaN8VAHwqpYA4S"
},
"rpc-addr": "0.0.0.0",
"rpc-port": 20002,
"fee-parameters": {},
"mode": "operator"
},
"evm_node_config": {
"rpc-addr": "0.0.0.0",
"rpc-port": 20004,
"mode": {
"rollup_node_endpoint": "http://127.0.0.1:20002"
}
},
}

Note that the octez-evm-node’s port is 20004 which we exposed in the Docker command above. In order to connect a MetaMask wallet to the EVM Rollup you will need the port and the chain_id. You can query the octez-evm-node using Ethereum RPC calls. For example the following call will return the chain_id which is 123123.

curl -s -H "Content-Type: application/json" -X POST \
--data "{\"jsonrpc\":\"2.0\",\"method\":\"net_version\",\"params\":[]}" \
http://localhost:20004

Setting Up MetaMask

For this demonstration, we will use MetaMask, a popular browser extension for interacting with EVM based protocols. Ensure you have the MetaMask extension installed in your browser. Visit the MetaMask website and follow the installation instructions.

In order to connect your MetaMask wallet to the EVM Rollup, click the Select a Network drop down menu on the top left. By default it shows “Ethereum Mainnet” click Add network.

Use the network name of your choice. For New RPC URL enter “http://localhost:20004”. For Chain ID enter “123123”. Finally use “XTZ” for the Currency symbol, then save.

The address in your MetaMask wallet will be your account address on the rollup. Record it.

evm_acc=0x798e0be76b06De09b88534c56EDF7AF339447e02
Setting Up MetaMask

Transferring Tez to the EVM Rollup

The simplest way to interact with a Flexesa sandbox is with the octez-client which is configured in the Docker container. Use the initclient command from the oxfordbox script to import the relevant addresses for this demo.

docker exec my-sandbox oxfordbox initclient
Tezos address added: tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb
Tezos address added: tz1aSkwEot3L2kmUvcoxzjMomb9mvBNuzFK6
Tezos address added: tz1YPSCGWXwBdTncK2aCctSZAXWvGsGwVJqU
Added contract evm-bridge: KT1Vq3vBnCNuds6YwjjcJeqBTaeqgTh52oQy
Added contract exchanger: KT1D3VK3BQ2rbpufqwacJU97wgQst7NyuST3
Added smart rollup evm: sr1DRk5qfiziibipQBVYS7PPtt4Abk8k5bny

The three tz1 addresses above are for Alice, Bob and the baker account. The exchanger contract will mint and burn tez tickets for use on the EVM Rollup. The evm-bridge contract transfers tez tickets between the accounts on layer one and the smart-rollup. Finally, the sr1 address is for the evm smart-rollup. Record it.

sr_addr=sr1DRk5qfiziibipQBVYS7PPtt4Abk8k5bny

To simplify making octez-client calls, it helps to alias the octez-client in the container.

alias tcli='docker exec my-sandbox octez-client'

Now send tez from Alice to the evm_acc on the rollup with a call to the “deposit” entrypoint of the evm-bridge contract.

tcli transfer 42 from alice to evm-bridge --entrypoint "deposit" --arg "(Pair \"${sr_addr}\" ${evm_acc})" --burn-cap 1

If you check the balance for Alice again it will be debited 42 tez. Next, check your MetaMask wallet extension to see the new balance.

Transferring Tez to the EVM Rollup

Originating a Contract with Remix

This section will walk through using Remix (an Ethereum IDE) to write, deploy and interact with smart contracts on the EVM Rollup. Visit the Remix website.

This demo will use the “HelloWorld” example contract generated by Remix when you click Start Coding. You will find the contract in the file menu on the left under Contracts. Select HelloWorld.sol, then select the Solidity Compiler in the left side bar. Now click Compile HelloWorld.sol.

Now switch to the Deploy & Run Contracts panel. At the top of this panel, change the Environment to “Injected Provider - MetaMask.” Click the orange Deploy button.

Remix has a console at the bottom of the page. You can review the output of the operation there. You will also see a “contract deployed” operation confirmation in your MetaMask extension.

Originating a Contract with Remix

Withdrawing Tez to Layer One

The EVM Rollup has a smart contract for bridging Tez tickets back to layer one. Use Remix to interact with it and send tez back to the and account on layer one.

First in the file explorer menu, create a new my.abi file and paste the following lines in it.

[
{
"type": "function",
"name": "withdraw_base58",
"constant": false,
"payable": true,
"inputs": [
{ "type": "string", "name": "target" }
]
}
]

The withdrawal contract address is:

0x0000000000000000000000000000000000000020

In the field titled Load contract from Address enter the contract address and then click At Address.

Finally, toward the bottom of the panel under Deployed Contracts, find the withdrawal contract address and click the angle bracket > to unfold the contract interaction menu. Enter Alice’s “tz1” address in this field titled string target and click the red withdraw_base58 button.

The MetaMask extension should ask you to confirm. After a short wait the operation should also be “confirmed” by the octez-evm-node and your MetaMask account balance will be debited the amount sent.

This operation creates an “outbox message” which passes data between smart- rollups and Tezos’ layer one. The outbox message will need to be executed by the octez-client in order to complete the transfer to Alice’s account on Tezos’ layer one.

Withdrawing Tez to Layer One

Executing the Smart-Rollup Outbox Message

Once the outbox message is created by the EVM Rollup, there are a few steps to executing the message and completing the withdrawal process. This section will describe that process and provide an example script to help execute the steps.

Before the outbox message can be executed, you will have to wait for a period of time called the challenge window. The challenge window is part of the mechanism by which smart-rollup participants keep each other honest. As the smart-rollup progresses, rollup operators will publish “commitments” to Tezos’ layer one. Commitments are considered “cemented” after the challenge window has passed without a refutation of that commitment. Funds transferred from the smart-rollup to layer one remain locked during the challenge window. In Flextesa the challenge window is 30 blocks (about one minute with the default block-time). Once the commitment containing the outbox message is cemented, the outbox message can be executed, completing the withdrawal.

In order to execute a smart-rollup outbox message you’ll need the smart-rollups sr1 address, the outbox message proof and corresponding smart-rollup commitment hash. The proof and the commitment hash are extracted via an RPC call to octez-smart-rollup-node at the following url: global/block/head/helpers/proofs/outbox/${level}/messages?index=0".

Here is the sequence of steps:

  1. Find the block level at which the smart-rollup first published the commitment containing the outbox message.
  2. Wait for the commitment at that block level to cement.
  3. Get the message proof and commitment hash.
  4. Execute the outbox message.
  5. Check the receiving account balance.

The Withdrawal Script linked below is designed to interact with the EVM Rollup running in a Docker container, as described above. It may require some configuration for your environment.

Withdrawal Script

You can run the individual commands manual or simply run the script without an argument and it will complete the withdrawal process. For example running this script after executing the withdrawal contract on the EVM Rollup should result in the following output:

$ withdrawal.sh
[Withdrawal:] Alice's starting balance: 1873459.924145 ꜩ
[Withdrawal:] Searching for the outbox message in the last 300 levels...
[Withdrawal:] The evm-rollup outbox message was found in the commit at level 2608.
[Withdrawal:] Waiting for the commitment to cement...
[Withdrawal:] The commitment at level 2608 is cemented.
[Withdrawal:] Executing the outbox message...
Node is bootstrapped.
Estimated gas: 5675.072 units (will add 100 for safety)
Estimated storage: no bytes added
Operation successfully injected in the node.
Operation hash is 'ooWzMypKZr68WMcsgK81MouhbqqDpbHfRhTCmToCztvVYzrWEWU'
Waiting for the operation to be included...
Operation found in block: BLN8oSXQrYnZePPPhDhmCArqjBDptAKBNTgjqFeLVoFkgdvD7eQ (pass: 3, offset: 0)
This sequence of operations was run:
Manager signed operations:
From: tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb
Fee to the baker: ꜩ0.001881
Expected counter: 11
Gas limit: 5776
Storage limit: 0 bytes
Balance updates:
tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb ... -ꜩ0.001881
payload fees(the block proposer) ....... +ꜩ0.001881
Smart rollup output message execution:
Address: sr1FZ28jb2RH6a6Dkcui7bL4ngW5wBjHqC4W
Cemented commitment: src148DZCs9n5pFK9XTLrC2pFZd3ehLyvHBxvduNgntwGxbp6qa7RY
This smart output message execution was successfully applied
Consumed gas: 4399.312
Ticket updates:
Ticketer: KT1SBdbAo2tMmdoM83rLXvq1qaKhZmRBEMwP
Content type: (pair nat (option bytes))
Content: (Pair 0 None)
Account updates:
sr1FZ28jb2RH6a6Dkcui7bL4ngW5wBjHqC4W ... -200000000
Internal operations:
Internal Transaction:
Amount: ꜩ0
From: sr1FZ28jb2RH6a6Dkcui7bL4ngW5wBjHqC4W
To: KT1SBdbAo2tMmdoM83rLXvq1qaKhZmRBEMwP
Entrypoint: burn
Parameter: (Pair 0x00006b82198cb179e8306c1bedd08f12dc863f328886
(Pair 0x01c1120a04adcc03f18aee7a60f7ff8a336d7b9abc00 (Pair (Pair 0 None) 200000000)))
This transaction was successfully applied
Updated storage: Unit
Storage size: 483 bytes
Consumed gas: 1175.694
Internal Transaction:
Amount: ꜩ200
From: KT1SBdbAo2tMmdoM83rLXvq1qaKhZmRBEMwP
To: tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb
This transaction was successfully applied
Consumed gas: 100
Balance updates:
KT1SBdbAo2tMmdoM83rLXvq1qaKhZmRBEMwP ... -ꜩ200
tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb ... +ꜩ200

The operation has only been included 0 blocks ago.
We recommend to wait more.
Use command
octez-client wait for ooWzMypKZr68WMcsgK81MouhbqqDpbHfRhTCmToCztvVYzrWEWU to b
92F3bzNqq7MUYSRBQWgzX7CyoNVm5K82
and/or an external block explorer.
[Withdrawal:] Alice's ending balance 1873659.922264 ꜩ

Notice that executing the outbox message calls the “burn” entrypoint of the exchanger contract. This is followed up by a transaction sending tez from the exchanger contract back to Alice’s tz1 address, completing the round trip.

A final note regarding a time limit on smart rollup outbox messages. The octez-smart-rollup-node doesn’t retain cemented commits indefinitely. Commits are eventually pruned and the message will no longer be valid for execution. In the EVM Rollup sandbox, expiration occurs three hundred blocks after they have been cemented (approximately 10 minutes).

Thanks!

The EVM Rollup Sandbox in Flextesa offers a simplified and comprehensive environment for testing and development of projects looking to leverage the power of Tezos and Ethereum ecosystems. . For more detailed instructions and additional information, visit the gitlab repository. We’re excited to see what you build with this new feature.

Oxhead Alpha is no longer maintaining Flextesa. This will be our last contribution for the foreseeable future. We sincerely thank you for following our work on this project!

--

--