You can't deploy an Ethereum smart contract on Nervos and then have Tron users interact with it, can you? Yes, you can!
In this tutorial you will install a Tron wallet, and then make a function call to the Ethereum smart contract that you previously deployed on the Nervos' Layer 2 Testnet. We will show you how Nervos' flexibility can be used to allow your dapp to support wallets from other blockchain ecosystems, and allow their users to interact with Ethereum smart contracts even though they were never designed to do so.
Note: Before starting the tasks, it is recommended that you review the Task Submission section so you know what materials you will need to provide to judges to review your task submission.
The general flow for this task is as follows:
- Create and fund a Layer 1 CKB account.
- Install a Tron Wallet and create a Tron account.
- Create and fund a Nervos Layer 2 account using your Tron account.
- Prepare and deploy a Solidity smart contract to Nervos Layer 2.
- Use the example code to make a smart contract call using your Tron account.
Some of these steps were completed in previous tasks, and you can reuse that work so you don't have to do it again. We'll point this out in the steps whenever it is possible.
Before you begin this task you will need to setup Godwoken Examples tool package. This should already be setup from previous tasks, but if it isn't for any reason, you can set it up again using the instructions here.
The first step is to create an account on the Nervos CKB Layer 1 Testnet, fund it with some CKBytes, then export the private key for the account so it can be provided to other scripts.
This can be accomplished easily using the ckb-cli command line tool that is included with the CKB Node software. Free Testnet CKBytes can be obtained by using the Nervos Faucet.
For complete instructions on completing this step, repeat the steps from Task 1.
In previous tasks we used a MetaMask account, but this time we will use a Tron account.
In this step, you need to install the TronLink wallet and create an account. Follow the instructions in this tutorial to do so.
In this step, we will export your private key so it can be used with the tooling in later steps. Follow the instructions in this tutorial to do so.
In this step, you must make a deposit of CKBytes from Layer 1 to Layer 2. This step is necessary for Godwoken to create the user's Layer 2 account. We did so previously using an Ethereum MetaMask account, and now we will do the same with a Tron account from the TronLink wallet.
This deposit can be made using the example script code provided in the tutorial below. Make sure you have your Layer 1 private key available since it will be needed by the example script.
For instructions on completing this step using Tron wallet, please follow the steps in this tutorial.
In order to execute a function call on a smart contract, it must be deployed, and you must have the ABI that was generated when the code was originally compiled. "ABI" stands for Application Binary Interface, and it contains the information required by an application to interface and call functions on the smart contract.
Deploying an Ethereum smart contract on Layer 2 was accomplished in Task 2. You can reuse this smart contract without having to repeat Task 2. If it is no longer available, please repeat the steps in Task 2.
The example smart contract is SimpleStorage.sol
, and the corresponding ABI value can be found in 2-deploy-contract/build/contracts/SimpleStorage.json
after the contract is compiled. Below is the ABI value which has been extracted from this file. If you used a different smart contract, yours may be different.
[
{
"inputs": [],
"stateMutability": "payable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "x",
"type": "uint256"
}
],
"name": "set",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "get",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]
The SimpleStorage contract has also been deployed to Testnet at the address below. You can optionally use this for testing purposes, but the judges will require you to use your own contract to complete this task.
0xC46e27169824290EcaEf6E14503C1a6DE72d41B0
Next, we will use the example code to make a function call in your smart contract. Open the file gw-gitcoin-instruction/src/examples/11-tron/index.mjs
in an editor of your choosing.
This example code is similar to that from Task 3, where we made function calls to a deployed Ethereum smart contract using a MetaMask account. Now we will do the same, but with a Tron account.
Replace the following values in index.mjs
.
The first thing you will need to do is update index.mjs
with your Tron address. You can get Tron address from your Tron wallet. Replace <YOUR_TRON_ADDRESS>
with this value.
const TRON_ADDRESS = '<YOUR_TRON_ADDRESS>';
The second thing you will need to do is update index.mjs
with the private key that matches the Tron address you specified.
Make sure you use your Tron private key for Layer 2, not your Nervos CKB Layer 1 private key, or your Ethereum account private key. Replace <YOUR_TRON_PRIVATE_KEY>
with this value. Always make sure your private key is prefixed with "0x".
const ACCOUNT_PRIVATE_KEY = '<YOUR_TRON_PRIVATE_KEY>';
Next, add your contract ABI to the script by replacing <YOUR_CONTRACT_ABI>
with the ABI value from the JSON file which was generated during compilation.
Note: The
CONTRACT_ABI
constant is expecting an array with your ABI as index 0. Make sure this is a data structure, just like it is inSimpleStorage.json
, and does not get input as a string.
const CONTRACT_ABI = [<YOUR_CONTRACT_ABI>]; // Array
Replace <YOUR_CONTRACT_ADDRESS>
with the address of the Ethereum contract you will be making calls to. This value should be a hex string that was returned when the after deploying the contract.
const CONTRACT_ADDRESS = '<YOUR_CONTRACT_ADDRESS>';
Locate <YOUR_READ_FUNCTION_NAME>
within the readCall()
function. This must be replaced with function name from your contract that is used for reading.
const callResult = await contract.methods.<YOUR_READ_FUNCTION_NAME>().call();
Locate <YOUR_WRITE_FUNCTION_NAME>
within the writeCall()
function. This must be replaced with function name from your contract that is used for writing.
const callData = contract.methods.<YOUR_WRITE_FUNCTION_NAME>().encodeABI();
After all values have been replaced, use the following commands in a console to execute the script.
cd ~/projects/gw-gitcoin-instruction/src/examples/11-tron
node index.mjs
Example Output (click to expand)
➜ node index.mjs
Using Tron address: TFrSJCrSJai8H2Kc32TP3nEzuWsXu8YnUJ
Calling contract...
Read call result: 400
{
tx: {
from: '0x4088F10C8D7EC48D19035D8C0709397E2FEC18C3',
to: '0x3E3b7616812290B60ceEcF412C9CDf941Da841A9',
nonce: '0x0',
gasPrice: '0x0',
gas: '0x271110',
value: '0x0',
data: '0x60fe47b10000000000000000000000000000000000000000000000000000000000000309'
}
}
Write call transaction hash: 0x03120a01d066fb973f4cbce4eb70b684312c05a373a8e99218b349bb6de81eae
Waiting for tx receipt doesn't work for Tron calls, but if transaction was submitted then you can check the smart-contract state after 120s and the state should be changed successfully. Waiting 2 minutes...
Write call finished.
Read call result: 777
If you've seen transaction hash and the smart contract state changed then congratulations! You have successfully issued a smart contract write call on Nervos Layer 2.
To complete the tasks, you will need to submit the following materials for review by the judges:
- A screenshot of the accounts you created (
account list
) inckb-cli
. - A link to the Layer 1 address you funded on the Testnet Explorer.
- A screenshot of the console output immediately after you have successfully submitted a CKByte deposit to your Tron account on Layer 2.
- A screenshot of the console output immediately after you have successfully issued a smart contract calls on Layer 2.
- The
transaction hash
of the "Contract call" from the console output (in text format). - The
contract address
that you called (in text format). - The ABI for contract you made a call on (in text format).
- Your Tron address (in text format).