2 - ERC20 Contract Deployment and Cross Contract Call
The L1X chain operates using two virtual machines: l1x-vm powered by the ebpf virtual machine and l1x-evm based on the Ethereum Virtual Machine (EVM).
In this walkthrough, we demonstrate how to deploy an ERC20 contract using the creationCode20.txt file to l1x-evm and interact with the contract functions via l1x-vm. This interaction is achieved by making a call to the l1x_evm_cross_contract contract functions.
To facilitate interaction with both virtual machines, users can utilize the L1X node client JSON RPC.
The contract code for cross calls, named l1x_evm_cross_contract, is located in the l1x-contracts directory as shown below:
exa -T -L 1 ./l1x-contracts
./l1x-contracts
└── l1x_evm_cross_contractAdditionally, the pre-built bytecode blob for the ERC20 contract is stored in the creationCode20.txt file within the l1x-evm-artifacts directory:
exa -T -L 1 ./l1x-evm-artifacts
./l1x-evm-artifacts
└── creationCode20.txtNote: The toolchain for creating the bytecode blob for l1x-evm is currently in progress and is expected to be released soon as part of the l1x-toolkit release.
1.1. Create an empty folder for this demonstration:
$ mkdir -p $HOME/l1x-demo-home/1.2. Change your current directory to the newly created folder:
$ cd $HOME/l1x-home/l1x-demo-home/
2.1. Make sure you can access the
l1x-forgetool from your command line. If you don't havel1x-forgeinstalled, follow the instructions in Step 2: Checking the L1X Tool before proceeding.2.2. Use the
l1x-forgecommand to create a new project workspace. We'll name it "l1x_demo02_erc20_cross_call" and use the template "l1x-erc20-cc-call":$ l1x-forge new --name l1x_demo02_erc20_cross_call --template l1x-erc20-cc-call2.3. After running the command, you'll receive a confirmation message indicating the successful creation of the "l1x_demo02_erc20_cross_call" contract:
Created contract l1x_demo02_erc20_cross_call2.4. Your workspace will now be populated with content from the template.
$ exa -T -L 1 ./l1x_demo02_erc20_cross_call ./l1x_demo02_erc20_cross_call ├── Cargo.lock ├── Cargo.toml ├── devbox.json ├── devbox.lock ├── devnet-services-dc.yml ├── l1x-conf ├── l1x-contracts ├── l1x-evm-artifacts ├── l1x-evm-contracts ├── package.json ├── process-compose-devnode.yaml ├── README.md ├── rust-toolchain.toml └── rustfmt.toml
3.1. Introduction to Devbox Shell and Workflow Commands
If you're new to the l1x-sde template workspace, it's a good idea to familiarize yourself with the basics of the devbox shell and workflow commands. This will help you get started more smoothly. You can review the following links for an overview:
3.2. Default Commands to Begin With
To start using the workspace, there are some default commands you can use:
Activate the Shell: To access the devbox shell, simply enter the following command in your terminal:
$ devbox shellList Default Commands: To see a list of the built-in default commands available in the devbox shell, you can use the following command:
(devbox)$ devbox run -l | sort * 01_init_setup * 01_teardown_setup * 02_check_chain_state * 02_check_devnet_db_state * 02_prune_devnode * 02_start_devnode * 02_stop_devnode * 10_01_compile_ebpf * 10_compile_ebpf_cmd * 11_clean_logs * 11_clean_objs * 18_cli_ro_call_cmd * 18_cli_ro_get_balanceof_ava * 18_cli_ro_get_balanceof_cc_contract * 18_cli_ro_get_balanceof_super * 18_cli_sub_txn_cc_transfer_to_cc_contract * 18_cli_sub_txn_erc20_transfer_to_cc_contract * 40_cli_deploy_ebpf * 40_cli_deploy_ebpf_cmd * 41_cli_init_ebpf * 41_cli_vm_sub_txn_cmd * 60_forge_install_ebpf_cmd_force_deploy * 61_forge_install_ebpf_cmd_reuse_deploy * 62_forge_install_evm_cmd_force_deploy * 80_00_forge_install_ebpf_all * 80_01_forge_install_ebpf_erc20_cross_call * 81_01_forge_install_evm_erc20 * 82_01_forge_install_evm_all Available scripts:
Initialize the Workspace: To prepare your workspace for building and testing, run:
(devbox)$ devbox run 01_init_setup
Now you have all the necessary tools and packages to work with the demo template workspace.
Now, let's guide you through the process of building the smart contracts.
4.1 Compiling the Contract for
l1x-vm
To compile the l1x_evm_cross_contract contract, simply use this command:
(devbox)$ devbox run 10_01_compile_ebpfRunning this command will compile the contract for you and save the compiled files in the ./l1x-artifacts folder automatically.
After executing the command, you'll discover the following files in the ./l1x-artifacts folder:
```shell
exa -T -L 1 ./l1x-artifacts
./l1x-artifacts
├── l1x_evm_cross_contract.base64
├── l1x_evm_cross_contract.ll
├── l1x_evm_cross_contract.o
├── l1x_evm_cross_contract.versioned.ll
└── l1x_evm_cross_contract.wasm
```4.2 Compiling the Contract for
l1x-evm
For this demonstration, we're simplifying the process by using a pre-built EVM bytecode image, eliminating the need for a build process. To access the relevant file, execute this command:
(devbox)$ exa -T ./l1x-evm-artifacts
./l1x-evm-artifacts
└── creationCode20.txtThat's it! We've successfully completed the steps for building smart contracts.
In this step, we will walk you through the process of configuring local development l1x-chain network.
5.1 Choose the Chain Type: To begin, select the
"L1X_CFG_CHAIN_TYPE": "local_devnet"option. Next, open a new terminal and activate the devbox shell:$ devbox shell5.2 Start the Devnode Services: While in the devbox shell, run the following command:
(devbox)$ devbox run 02_start_devnode5.3 Wait for Services to Initialize: After executing the previous command, please wait for approximately 160 seconds. During this time, the services will start up and become operational. You will also observe the L1X node beginning to produce blocks.
5.5 Troubleshooting: Occasionally, we might encounter a problem where the
l1x-node-clientserver and thecassandraDB service do not sync properly, as indicated by the state shown in the image below.

To fix this issue and get your setup back on track, follow these simple steps:
(devbox)$ devbox run 02_stop_devnode (devbox)$ devbox run 02_prune_devnode (devbox)$ devbox run 02_start_devnode
These commands will help reset and restart the necessary components. Your setup should work smoothly after completing these steps.
5.5 Troubleshooting: Occasionally, we might encounter a problem where the
l1x-node-clientserver and thecassandraDB service do not sync properly, as indicated by the state shown in the image below.
To fix this issue and get your setup back on track, follow these simple steps:
(devbox)$ devbox run 02_stop_devnode (devbox)$ devbox run 02_prune_devnode (devbox)$ devbox run 02_start_devnode
These commands will help reset and restart the necessary components. Your setup should work smoothly after completing these steps.
In this section, we'll walk you through the process of deploying and creating an instance of the erc20 contract on the l1x-evm platform, as well as deploying and creating an instance of the l1x_evm_cross_contract.o contract on the l1x-vm platform.
We will use the default super account, which is defined in the l1x-conf/l1x_dev_wallets.yaml configuration file. The super account acts as the owner or administrator for the contracts we deploy.
6.1: Deploying and Creating an Instance of the
erc20Contract onl1x-evm
To deploy the compiled erc20 contract, follow these steps:
Run the command:
(devbox)$ devbox run 82_01_forge_install_evm_allTake note of the
L1XEVM_DEPLOYaddress displayed in the output. We'll call it theerc20_instance_address, and you'll need it for interacting with the contract.Update the following JSON payload transaction files with this address:
./l1x-conf/scripts/011-01-uc-init-erc20-cross-call.json
./l1x-conf/scripts/013-01-test-evm-erc20-transfer.json6.2: Deploying the
l1x_evm_cross_contract.oContract onl1x-vm
To deploy the compiled l1x_evm_cross_contract.o contract, follow these steps:
Take note of the
"address"displayed in the output. We'll call it theerc20_cross_call_deploy_address, which you'll need for contract instance creation.Update the following JSON payload transaction file with this address:
./l1x-conf/scripts/011-01-uc-init-erc20-cross-call.json
6.3: Creating an Instance from the Deployed
l1x_evm_cross_contract.oContract onl1x-vm
To create an instance from the compiled l1x_evm_cross_contract.o contract, follow these steps:
Update the JSON payload file located at
./l1x-conf/scripts/011-01-uc-init-erc20-cross-call.json.
Execute the following command:
(devbox)$ devbox run 41_cli_init_ebpfTake note of the
"address"displayed in the output. We'll call it theerc20_cross_call_instance_address, which you'll need for contract instance creation.Update the following JSON payload transaction files with this address:
./l1x-conf/scripts/012-01-test-vm-cc-erc20-balance-of.json
./l1x-conf/scripts/012-02-test-vm-cc-erc20-transfer.json
./l1x-conf/scripts/012-03-test-vm-cc-erc20-balance-of-ava.json
./l1x-conf/scripts/l1x-conf/scripts/012-04-test-vm-cc-erc20-balance-of-cc_contract.jsonNow you have successfully deployed and created instances of the contracts on the respective platforms. You can use the provided addresses for further interactions with the contracts.
This section provides step-by-step examples to help you understand how the system functions in real-life scenarios.
Use-Case 1: Checking Token Balance
In this example, we'll show you how to check the balance of an ERC20 token for three accounts: super, erc20_cross_call_instance_address, and ava. We'll achieve this by using a feature known as "cross-contract call," which allows interaction between the l1x-vm and l1x-evm.
Use-Case 2: Transferring Tokens
In this scenario, we want to transfer tokens to the address erc20_cross_call_instance_address from the super account.
Use-Case 3: Confirming Transaction Success
In this final example, we'll revisit the steps from Use-Case 1 to confirm the success status of the transaction initiated in Use-Case 2.
Understanding these straightforward use-cases will help you grasp how the "cross-contract call" feature works effectively.
Here are the steps:
1. Begin by initiating a balance request to a contract located at the address `erc20_cross_call_instance_address` within the `l1x-vm`.
2. This request will be internally directed to another contract located at `erc20_instance_address`, which is deployed on the `l1x-evm`.Now, let's check the balance for each of these accounts:
Checking Balance for Account
super
To check the balance for the super account, run the following command in your development environment:
(devbox)$ devbox run 18_cli_ro_get_balanceof_superYou'll get a result similar to the image below, with variations in the context-specific payload, address, and return values highlighted:
Checking Balance for Account
erc20_cross_call_instance_address
To check the balance for the erc20_cross_call_instance_address account, execute the following command:
(devbox)$ devbox run 18_cli_ro_get_balanceof_cc_contractYou'll get a result similar to the image below, with variations in the context-specific payload, address, and return values highlighted:
Checking Balance for Account
ava
Finally, to check the balance for the ava account, use the following command:
(devbox)$ devbox run 18_cli_ro_get_balanceof_avaYou'll get a result similar to the image below, with variations in the context-specific payload, address, and return values highlighted:
In this scenario, we aim to move tokens from the super account to the address known as erc20_cross_call_instance_address. Here are the steps to carry out this transfer:
Generate an ABI payload using the online ABI encoder tool, which you can access at this link. Fill in the required information for the
transfer()function, and then copy the encoded data to a JSON file located atl1x-conf/scripts/013-01-test-evm-erc20-transfer.json.
Note: When specifying the address, use erc20_cross_call_instance_address. In this context, this address is 0x4c8a5411e4dd41024673392050ab8928050e8c8d, and select a token amount of 1000.
Initiate a direct transaction to the contract found at
erc20_instance_address, which has been deployed onl1x-evm. Execute the following command:
(devbox)$ devbox run 18_cli_sub_txn_erc20_transfer_to_cc_contractYou will receive a result that resembles the image below. Please note that the specifics of the payload, address, and return values may vary depending on the context.
In this final example, we'll revisit the steps from Use-Case 1 to confirm the success status of the transaction initiated in Use-Case 2.
Checking Balance for Account
erc20_cross_call_instance_address
To check the balance for the erc20_cross_call_instance_address account, execute the following command:
(devbox)$ devbox run 18_cli_ro_get_balanceof_cc_contractYou'll get a result similar to the image below, with variations in the context-specific payload, address, and return values highlighted:
Last updated