Skip to content

Commit

Permalink
Merge pull request #13 from immutable/SMR-1773-axelar-local
Browse files Browse the repository at this point in the history
cleanup local axelar scripts for the Demo
  • Loading branch information
Benjimmutable authored Oct 30, 2023
2 parents ff42ce1 + ad21f38 commit 4a4f7fc
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 36 deletions.
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,25 @@ ENVIRONMENT="local"
./deploy.sh
```

4. Copy the config file with the correct addresses
4. Run the script that will send a `MAP_TOKEN` message
```shell
cp axelar-local-dev/chain-config/local.template.json axelar-local-dev/chain-config/local.json
yarn run execute evm/call-contract local Ethereum Polygon map
```

5. Run the script to execute the `axelar-local-dev/examples/evm/call-contract/index.js` file
5. (OPTIONAL) Check the token mapping has been populated using `cast`
```shell
yarn run execute evm/call-contract local Ethereum Polygon
source .env
cast call --rpc-url $CHILD_RPC_URL "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" "rootTokenToChildToken(address)(address)" "0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4"
```

6. Run the script that will send a `DEPOSIT` message
```shell
yarn run execute evm/call-contract local Ethereum Polygon deposit
```

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"
```
(Note: This assumed your address if the one associated with the above-specified private key)
171 changes: 147 additions & 24 deletions axelar-local-dev/examples/evm/call-contract/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,176 @@ 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('execute call-contract');
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)
} 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() {
console.log(destination.name)
console.log(`value at ${destination.name} is "${await destination.contract2.rootTokenToChildToken("0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4")}"`);
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 {
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()
const tx = await source.contract.mapToken(TOKEN, {value: fee})
await tx.wait()
await logValue();

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) {
console.log("======================================")
console.log("ATTEMPTING TO SEND `DEPOSIT` MESSAGE")
console.log("======================================")
console.log()

const depositAmount = ethers.utils.parseEther("0.1")
const userAddress = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
const basicTokenAbi = `
[
{
"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, 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(l1Balance).toString()} L1 token(s), and ${ethers.utils.formatEther(l2Balance).toString()} L2 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() === initialBal.toString()) {
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,
};
2 changes: 0 additions & 2 deletions axelar-local-dev/scripts/libs/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 0 additions & 2 deletions axelar-local-dev/scripts/libs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'))
Expand Down
3 changes: 0 additions & 3 deletions axelar-local-dev/scripts/runExecute.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@
"optionalDependencies": {
"@axelar-network/axelar-local-dev-aptos": "^2.1.1-alpha.4"
}
}
}

0 comments on commit 4a4f7fc

Please sign in to comment.