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_contract
Additionally, 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.txt
Note: 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-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-forge
tool from your command line. If you don't havel1x-forge
installed, follow the instructions in Step 2: Checking the L1X Tool before proceeding. -
2.2. Use the
l1x-forge
command 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-call
-
2.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_call
-
2.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 shell
-
List 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_ebpf
Running 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.txt
That'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 shell
-
5.2 Start the Devnode Services: While in the devbox shell, run the following command:
(devbox)$ devbox run 02_start_devnode
-
5.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.4 Verify DevNet Service Status: To ensure that everything is running smoothly, use the following command to check the service status:
(devbox)$ devbox run 02_check_chain_state
(devbox)$ devbox run 02_check_devnet_db_state
-
5.5 Troubleshooting: Occasionally, we might encounter a problem where the
l1x-node-client
server and thecassandra
DB 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
erc20
Contract onl1x-evm
To deploy the compiled erc20
contract, follow these steps:
-
- Run the command:
(devbox)$ devbox run 82_01_forge_install_evm_all
-
- Take note of the
L1XEVM_DEPLOY
address displayed in the output. We'll call it theerc20_instance_address
, and you'll need it for interacting with the contract.
- Take note of the
-
- 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.json
-
6.2: Deploying the
l1x_evm_cross_contract.o
Contract onl1x-vm
To deploy the compiled l1x_evm_cross_contract.o
contract, follow these steps:
-
Update the JSON payload in the file
l1x-conf/scripts/010-01-uc-deploy-erc20-cross-call.json
with the artifact information. -
Execute the following command:
(devbox)$ devbox run 40_cli_deploy_ebpf
-
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.o
Contract 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
.
- Update the JSON payload file located at
-
- Execute the following command:
(devbox)$ devbox run 41_cli_init_ebpf
-
- Take 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.
- Take note of the
-
- 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.json
Now 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_super
You'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_contract
You'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_ava
You'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_contract
You 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_contract
You'll get a result similar to the image below, with variations in the context-specific payload
, address
, and return values
highlighted: