From 39f5d40a3cb52af11aa36d89f51ba08878fd67c8 Mon Sep 17 00:00:00 2001 From: Benjamin Patch Date: Thu, 26 Oct 2023 13:48:47 +1100 Subject: [PATCH 1/3] cleanup for the Demo --- README.md | 22 ++- .../examples/evm/call-contract/index.js | 151 +++++++++++++++--- axelar-local-dev/scripts/libs/execute.js | 2 - axelar-local-dev/scripts/libs/utils.js | 2 - axelar-local-dev/scripts/runExecute.js | 3 - package.json | 2 +- 6 files changed, 149 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 8acd6cc0..8102b1b9 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,25 @@ CHILD_GAS_SERVICE_ADDRESS="0xC573c722e21eD7fadD38A8f189818433e01Ae466" cp axelar-local-dev/chain-config/local.template.json axelar-local-dev/chain-config/local.json ``` -5. Run the script to execute the `axelar-local-dev/examples/evm/call-contract/index.js` file +5. Run the script that will send a `MAP_TOKEN` message ```shell -yarn run execute evm/call-contract local Ethereum Polygon +yarn run execute evm/call-contract local Ethereum Polygon map ``` + +6. (OPTIONAL) Check the token mapping has been populated using `cast` +```shell +source .env +cast call --rpc-url $CHILD_RPC_URL "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" "rootTokenToChildToken(address)(address)" "0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4" +``` + +7. Run the script that will send a `DEPOSIT` message +```shell +yarn run execute evm/call-contract local Ethereum Polygon map +``` + +8. (OPTIONAL) Check the tokens have been deposited using `cast` +```shell +source .env +cast call --rpc-url $CHILD_RPC_URL "0x3b39f73D7De57Ed2Fe85C0F30374D839dc625b93" "balanceOf(address)(uint256)" "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +``` +(Note: This assumed your address if the one associated with the above-specified private key) diff --git a/axelar-local-dev/examples/evm/call-contract/index.js b/axelar-local-dev/examples/evm/call-contract/index.js index 81663ef4..e58bbf9b 100644 --- a/axelar-local-dev/examples/evm/call-contract/index.js +++ b/axelar-local-dev/examples/evm/call-contract/index.js @@ -4,53 +4,158 @@ const util = require('util') const { utils: { deployContract }, } = require('@axelar-network/axelar-local-dev'); +const { ethers } = require('ethers'); const ExecutableSample = rootRequire('./artifacts/examples/evm/call-contract/ExecutableSample.sol/ExecutableSample.json'); - -async function deploy(chain, wallet) { - console.log(`Deploying ExecutableSample for ${chain.name}.`); - chain.contract = await deployContract(wallet, ExecutableSample, [chain.gateway, chain.gasService]); - chain.wallet = wallet; - console.log(`Deployed ExecutableSample for ${chain.name} at ${chain.contract.address}.`); -} +const TOKEN = "0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4" +const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" async function execute(chains, wallet, options) { + console.log("======================================") + console.log("ATTEMPTING TO SEND `MAP_TOKEN` MESSAGE") + console.log("======================================") + console.log() - console.log('execute call-contract'); - const args = options.args || []; + // const args = options.args || []; const { source, destination, calculateBridgeFee } = options; - const message = args[2] || `Hello ${destination.name} from ${source.name}, it is ${new Date().toLocaleTimeString()}.`; + let functionToCall = options.args[2] + if (functionToCall === "map") { + await map(source, destination, calculateBridgeFee) + } else if (functionToCall === "deposit") { + await deposit(source, destination, calculateBridgeFee) + } +} +async function map(source, destination, calculateBridgeFee) { async function logValue() { - console.log(destination.name) - console.log(`value at ${destination.name} is "${await destination.contract2.rootTokenToChildToken("0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4")}"`); + let childTokenAddress = await destination.contract2.rootTokenToChildToken(TOKEN); + console.log(`The L1 => L2 token mapping for token ${TOKEN.slice(0,8)}... is ${childTokenAddress.slice(0,8)}...`) + if (childTokenAddress === ZERO_ADDRESS){ + console.log("This is empty, indicating that the L1 token hasn't been deployed yet on L2. :( :(") + } else { + console.log(childTokenAddress) + console.log("This is no longer the zero address. The token has been mapped successfully!!! 📜 ☕ 📜 ☕ 📜 ☕ 📜 ☕ 📜 ☕ ") + } + console.log() } - console.log('--- Initially ---'); await logValue(); + console.log(`Calculating service fee...`); + console.log() + const fee = await calculateBridgeFee(source, destination); - console.log('fee',fee); + console.log(`Calling mapToken with a service fee of ${fee} ETH`); + console.log() + await source.contract.mapToken(TOKEN, {value: fee}) + + const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + + while ((await destination.contract2.rootTokenToChildToken(TOKEN)) === ZERO_ADDRESS) { + console.log('Waiting...'); + console.log(); + await sleep(1000); + } + + await logValue(); +} + +async function deposit(source, destination, calculateBridgeFee) { + const depositAmount = ethers.utils.parseEther("0.1") + const userAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + const balanceOfAbi = ` + [ + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] + ` + + let l2TokenAddress = await destination.contract2.rootTokenToChildToken(TOKEN); + if (l2TokenAddress == ZERO_ADDRESS) { + console.log("The L1 token hasn't been mapped to L2 yet. Please run the `map` first first."); + process.exit(1); + } + + // User ethers to call the balanceOf function on the TOKEN contract + let l2TokenContract = new ethers.Contract(l2TokenAddress, balanceOfAbi, destination.contract.signer) + let l1TokenContract = new ethers.Contract(TOKEN, balanceOfAbi, source.contract.signer) + + async function logValue() { + let l2Balance = await l2TokenContract.balanceOf(userAddress) + let l1Balance = await l1TokenContract.balanceOf(userAddress) + console.log(`The user currently has ${ethers.utils.formatEther(l2Balance).toString()} L2 token(s), and ${ethers.utils.formatEther(l1Balance).toString()} L1 token(s)`) + console.log() + } + + await logValue(); + + console.log("Calling ERC20 approve...") + console.log() + + await l1TokenContract.approve(source.contract.address, depositAmount); + + console.log(`Calculating service fee...`); + console.log() + + const fee = await calculateBridgeFee(source, destination); - console.log("Calling mapToken"); - // const tx = await source.contract.deposit("0x38C50773CdA2E79a9217f40d63A8faF8fb0D4d73", "9999", {value: fee}) - const tx = await source.contract.mapToken("0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4", {value: fee}) - await tx.wait(); + console.log(`Calling deposit with ${ethers.utils.formatEther(depositAmount).toString()} tokens, and a service fee of ${fee} ETH`); + console.log() + await source.contract.deposit(TOKEN, depositAmount, {value: fee}) const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); - while ((await destination.contract2.rootTokenToChildToken("0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4")) == "0x0000000000000000000000000000000000000000") { + while ((await l2TokenContract.balanceOf(userAddress)).toString() === "0") { console.log('Waiting...'); - console.log(`value at ${destination.name} is "${await destination.contract2.rootTokenToChildToken("0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4")}"`); - await sleep(3000); + console.log(); + await sleep(1000); } - console.log('--- After ---'); await logValue(); } module.exports = { - deploy, execute, }; \ No newline at end of file diff --git a/axelar-local-dev/scripts/libs/execute.js b/axelar-local-dev/scripts/libs/execute.js index b7444ca7..3f7654dc 100644 --- a/axelar-local-dev/scripts/libs/execute.js +++ b/axelar-local-dev/scripts/libs/execute.js @@ -50,9 +50,7 @@ async function executeEVMExample(env, chains, args, wallet, example) { chain.gateway = new Contract(chain.gateway, AxelarGatewayContract.abi, connectedWallet); chain.gasService = new Contract(chain.gasService, AxelarGasServiceContract.abi, connectedWallet); - console.log('before getAddress') const tokenAddress = await chain.gateway.tokenAddresses('aUSDC'); - console.log('tokenAddress', tokenAddress) chain.usdc = new Contract(tokenAddress, IERC20.abi, connectedWallet); } diff --git a/axelar-local-dev/scripts/libs/utils.js b/axelar-local-dev/scripts/libs/utils.js index 5d12a305..c4871aaa 100644 --- a/axelar-local-dev/scripts/libs/utils.js +++ b/axelar-local-dev/scripts/libs/utils.js @@ -25,8 +25,6 @@ function getEVMChains(env, chains = []) { const selectedChains = chains.length > 0 ? chains : getDefaultChains(env); - console.log('selectedChains', selectedChains) - if (env === 'local') { return fs .readJsonSync(path.join(__dirname, '../../chain-config/local.json')) diff --git a/axelar-local-dev/scripts/runExecute.js b/axelar-local-dev/scripts/runExecute.js index 60b3cb3d..9d98de9c 100644 --- a/axelar-local-dev/scripts/runExecute.js +++ b/axelar-local-dev/scripts/runExecute.js @@ -15,9 +15,6 @@ const example = require(getExamplePath(exampleName)); // Get the wallet. const wallet = getWallet(); -console.log('run execute'); - - // This will execute an example script. The example script must have an `execute` function. if (exampleName.split('/')[0] === 'evm') { // Get the chains for the environment. diff --git a/package.json b/package.json index cf655a7c..fc7d8bd0 100644 --- a/package.json +++ b/package.json @@ -43,4 +43,4 @@ "optionalDependencies": { "@axelar-network/axelar-local-dev-aptos": "^2.1.1-alpha.4" } -} +} \ No newline at end of file From 4eb7dda8e87744ed618d4acf59b199436b752fff Mon Sep 17 00:00:00 2001 From: Benjamin Patch Date: Thu, 26 Oct 2023 14:16:14 +1100 Subject: [PATCH 2/3] More cleanup --- .../examples/evm/call-contract/index.js | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/axelar-local-dev/examples/evm/call-contract/index.js b/axelar-local-dev/examples/evm/call-contract/index.js index e58bbf9b..b7fa41f1 100644 --- a/axelar-local-dev/examples/evm/call-contract/index.js +++ b/axelar-local-dev/examples/evm/call-contract/index.js @@ -11,22 +11,24 @@ const TOKEN = "0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4" const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" async function execute(chains, wallet, options) { - console.log("======================================") - console.log("ATTEMPTING TO SEND `MAP_TOKEN` MESSAGE") - console.log("======================================") - console.log() - - // const args = options.args || []; const { source, destination, calculateBridgeFee } = options; let functionToCall = options.args[2] if (functionToCall === "map") { await map(source, destination, calculateBridgeFee) } else if (functionToCall === "deposit") { await deposit(source, destination, calculateBridgeFee) + } else { + console.error("final arg must be either `deposit` or `map`") + process.exit(1) } } async function map(source, destination, calculateBridgeFee) { + console.log("======================================") + console.log("ATTEMPTING TO SEND `MAP_TOKEN` MESSAGE") + console.log("======================================") + console.log() + async function logValue() { let childTokenAddress = await destination.contract2.rootTokenToChildToken(TOKEN); console.log(`The L1 => L2 token mapping for token ${TOKEN.slice(0,8)}... is ${childTokenAddress.slice(0,8)}...`) @@ -62,6 +64,11 @@ async function map(source, destination, calculateBridgeFee) { } async function deposit(source, destination, calculateBridgeFee) { + console.log("======================================") + console.log("ATTEMPTING TO SEND `DEPOSIT` MESSAGE") + console.log("======================================") + console.log() + const depositAmount = ethers.utils.parseEther("0.1") const userAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" const balanceOfAbi = ` @@ -122,6 +129,8 @@ async function deposit(source, destination, calculateBridgeFee) { let l2TokenContract = new ethers.Contract(l2TokenAddress, balanceOfAbi, destination.contract.signer) let l1TokenContract = new ethers.Contract(TOKEN, balanceOfAbi, source.contract.signer) + const initialBal = await l2TokenContract.balanceOf(userAddress) + async function logValue() { let l2Balance = await l2TokenContract.balanceOf(userAddress) let l1Balance = await l1TokenContract.balanceOf(userAddress) @@ -147,7 +156,7 @@ async function deposit(source, destination, calculateBridgeFee) { const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); - while ((await l2TokenContract.balanceOf(userAddress)).toString() === "0") { + while ((await l2TokenContract.balanceOf(userAddress)).toString() === initialBal.toString()) { console.log('Waiting...'); console.log(); await sleep(1000); From ad21f38426f2b9ede7e1eedf6ada621ec2ecde79 Mon Sep 17 00:00:00 2001 From: Benjamin Patch Date: Mon, 30 Oct 2023 11:33:18 +1100 Subject: [PATCH 3/3] Cleanup for demo --- README.md | 15 +++++---------- .../examples/evm/call-contract/index.js | 19 ++++++++++++++----- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 8102b1b9..c01ac134 100644 --- a/README.md +++ b/README.md @@ -148,28 +148,23 @@ CHILD_GAS_SERVICE_ADDRESS="0xC573c722e21eD7fadD38A8f189818433e01Ae466" ./deploy.sh ``` -4. Copy the config file with the correct addresses -```shell -cp axelar-local-dev/chain-config/local.template.json axelar-local-dev/chain-config/local.json -``` - -5. Run the script that will send a `MAP_TOKEN` message +4. Run the script that will send a `MAP_TOKEN` message ```shell yarn run execute evm/call-contract local Ethereum Polygon map ``` -6. (OPTIONAL) Check the token mapping has been populated using `cast` +5. (OPTIONAL) Check the token mapping has been populated using `cast` ```shell source .env cast call --rpc-url $CHILD_RPC_URL "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" "rootTokenToChildToken(address)(address)" "0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4" ``` -7. Run the script that will send a `DEPOSIT` message +6. Run the script that will send a `DEPOSIT` message ```shell -yarn run execute evm/call-contract local Ethereum Polygon map +yarn run execute evm/call-contract local Ethereum Polygon deposit ``` -8. (OPTIONAL) Check the tokens have been deposited using `cast` +7. (OPTIONAL) Check the tokens have been deposited using `cast` ```shell source .env cast call --rpc-url $CHILD_RPC_URL "0x3b39f73D7De57Ed2Fe85C0F30374D839dc625b93" "balanceOf(address)(uint256)" "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" diff --git a/axelar-local-dev/examples/evm/call-contract/index.js b/axelar-local-dev/examples/evm/call-contract/index.js index b7fa41f1..511f1403 100644 --- a/axelar-local-dev/examples/evm/call-contract/index.js +++ b/axelar-local-dev/examples/evm/call-contract/index.js @@ -31,7 +31,14 @@ async function map(source, destination, calculateBridgeFee) { async function logValue() { let childTokenAddress = await destination.contract2.rootTokenToChildToken(TOKEN); + let rootChainChildTokenAddress = await source.contract.rootTokenToChildToken(TOKEN); + console.log("LAYER 1:") + console.log(`The L1 => L2 token mapping for token ${TOKEN.slice(0,8)}... is ${rootChainChildTokenAddress.slice(0,8)}...`) + console.log() + console.log("LAYER 2:") console.log(`The L1 => L2 token mapping for token ${TOKEN.slice(0,8)}... is ${childTokenAddress.slice(0,8)}...`) + console.log() + if (childTokenAddress === ZERO_ADDRESS){ console.log("This is empty, indicating that the L1 token hasn't been deployed yet on L2. :( :(") } else { @@ -50,7 +57,9 @@ async function map(source, destination, calculateBridgeFee) { console.log(`Calling mapToken with a service fee of ${fee} ETH`); console.log() - await source.contract.mapToken(TOKEN, {value: fee}) + const tx = await source.contract.mapToken(TOKEN, {value: fee}) + await tx.wait() + await logValue(); const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); @@ -71,7 +80,7 @@ async function deposit(source, destination, calculateBridgeFee) { const depositAmount = ethers.utils.parseEther("0.1") const userAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" - const balanceOfAbi = ` + const basicTokenAbi = ` [ { "inputs": [ @@ -126,15 +135,15 @@ async function deposit(source, destination, calculateBridgeFee) { } // User ethers to call the balanceOf function on the TOKEN contract - let l2TokenContract = new ethers.Contract(l2TokenAddress, balanceOfAbi, destination.contract.signer) - let l1TokenContract = new ethers.Contract(TOKEN, balanceOfAbi, source.contract.signer) + let l2TokenContract = new ethers.Contract(l2TokenAddress, basicTokenAbi, destination.contract.signer) + let l1TokenContract = new ethers.Contract(TOKEN, basicTokenAbi, source.contract.signer) const initialBal = await l2TokenContract.balanceOf(userAddress) async function logValue() { let l2Balance = await l2TokenContract.balanceOf(userAddress) let l1Balance = await l1TokenContract.balanceOf(userAddress) - console.log(`The user currently has ${ethers.utils.formatEther(l2Balance).toString()} L2 token(s), and ${ethers.utils.formatEther(l1Balance).toString()} L1 token(s)`) + console.log(`The user currently has ${ethers.utils.formatEther(l1Balance).toString()} L1 token(s), and ${ethers.utils.formatEther(l2Balance).toString()} L2 token(s)`) console.log() }