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_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-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 have l1x-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 the cassandra 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.

  • 5.5 Troubleshooting: Occasionally, we might encounter a problem where the l1x-node-client server and the cassandra 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 on l1x-evm

To deploy the compiled erc20 contract, follow these steps:

  1. Run the command:

 (devbox)$ devbox run 82_01_forge_install_evm_all
  1. Take note of the L1XEVM_DEPLOY address displayed in the output. We'll call it the erc20_instance_address, and you'll need it for interacting with the contract.

  2. 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 on l1x-vm

To deploy the compiled l1x_evm_cross_contract.o contract, follow these steps:

  1. Update the JSON payload in the file l1x-conf/scripts/010-01-uc-deploy-erc20-cross-call.json with the artifact information.

  2. Execute the following command:

    (devbox)$ devbox run 40_cli_deploy_ebpf
  3. Take note of the "address" displayed in the output. We'll call it the erc20_cross_call_deploy_address, which you'll need for contract instance creation.

  4. 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 on l1x-vm

To create an instance from the compiled l1x_evm_cross_contract.o contract, follow these steps:

  1. Update the JSON payload file located at ./l1x-conf/scripts/011-01-uc-init-erc20-cross-call.json.

  1. Execute the following command:

(devbox)$ devbox run 41_cli_init_ebpf
  1. Take note of the "address" displayed in the output. We'll call it the erc20_cross_call_instance_address, which you'll need for contract instance creation.

  2. 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.

  1. 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.

  1. 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.

  1. 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:

  1. 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 at l1x-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.

  1. Initiate a direct transaction to the contract found at erc20_instance_address, which has been deployed on l1x-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:

Last updated