Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Update GMP Express #84

Merged
merged 17 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ jobs:
- name: Checkout code
uses: actions/checkout@v3
- name: Cache node_modules
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Test
timeout-minutes: 8
run: |
nohup sh -c "aptos node run-local-testnet --with-faucet" > nohup.out 2> nohup.err < /dev/null &
sleep 10
Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
"publish": "lerna publish from-package --yes",
"version": "lerna version --yes --exact",
"bootstrap": "lerna bootstrap",
"postinstall": "npm run bootstrap && lerna run build",
"postinstall": "lerna bootstrap",
"link": "lerna link",
"test": "lerna run test",
"update": "lernaupdate",
"update": "lerna update",
"test:core": "lerna exec --scope=@axelar-network/axelar-local-dev npm run test",
"test:near": "lerna exec --scope=@axelar-network/axelar-local-dev-near npm run test",
"test:aptos": "lerna exec --scope=@axelar-network/axelar-local-dev-aptos npm run test",
Expand Down
1 change: 0 additions & 1 deletion packages/axelar-local-dev-aptos/__tests__/aptos.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const { keccak256, toUtf8Bytes } = ethers.utils;
setLogger(() => undefined);

describe('aptos', () => {
jest.setTimeout(60000);
let client: AptosNetwork;
let evmNetwork: Network;

Expand Down
1 change: 1 addition & 0 deletions packages/axelar-local-dev-aptos/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ module.exports = {
},
testRegex: '/__tests__/.*\\.(test|spec)?\\.(ts)$',
transformIgnorePatterns: ['<rootDir>/node_modules/'],
testTimeout: 300000,
};
1 change: 1 addition & 0 deletions packages/axelar-local-dev-near/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ module.exports = {
'^.+\\.ts?$': 'ts-jest',
},
transformIgnorePatterns: ['<rootDir>/node_modules/'],
testTimeout: 300000,
};
2 changes: 0 additions & 2 deletions packages/axelar-local-dev-near/src/__tests__/near.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { createNearNetwork, NearNetwork } from '..';
import { Network, createNetwork, stopAll, deployContract, relay } from '@axelar-network/axelar-local-dev';
import { EvmRelayer } from '@axelar-network/axelar-local-dev/dist/relay/EvmRelayer';

jest.setTimeout(120000);

describe('near', () => {
let client: NearNetwork;

Expand Down
1 change: 1 addition & 0 deletions packages/axelar-local-dev/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ module.exports = {
'^.+\\.ts?$': 'ts-jest',
},
transformIgnorePatterns: ['<rootDir>/node_modules/'],
testTimeout: 300000,
};
4 changes: 2 additions & 2 deletions packages/axelar-local-dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
},
"homepage": "https://github.com/axelarnetwork/axelar-local-dev#readme",
"dependencies": {
"@axelar-network/axelar-cgp-solidity": "github:axelarnetwork/axelar-cgp-solidity#f668693",
"@axelar-network/axelar-gmp-sdk-solidity": "3.5.0",
"@axelar-network/axelar-cgp-solidity": "^5.0.0",
"@axelar-network/axelar-gmp-sdk-solidity": "^4.0.1",
npty marked this conversation as resolved.
Show resolved Hide resolved
"ethers": "^5.6.5",
"fs-extra": "^10.1.0",
"ganache": "^7.1.0",
Expand Down
40 changes: 8 additions & 32 deletions packages/axelar-local-dev/src/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import {
AxelarGasReceiverProxy,
ConstAddressDeployer,
Create3Deployer,
GMPExpressService,
GMPExpressProxyDeployer,
} from './contracts';
import { AxelarGateway__factory as AxelarGatewayFactory } from './types/factories/@axelar-network/axelar-cgp-solidity/contracts/AxelarGateway__factory';
import { AxelarGateway } from './types/@axelar-network/axelar-cgp-solidity/contracts/AxelarGateway';
import { AxelarGasService__factory as AxelarGasServiceFactory } from './types/factories/@axelar-network/axelar-cgp-solidity/contracts/gas-service/AxelarGasService__factory';
import { AxelarGasService } from './types/@axelar-network/axelar-cgp-solidity/contracts/gas-service/AxelarGasService';
import http from 'http';
import { EvmRelayer } from './relay/EvmRelayer';
import { evmRelayer } from './relay';

const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000';
const { defaultAbiCoder, arrayify, keccak256, toUtf8Bytes } = ethers.utils;
Expand All @@ -43,10 +43,9 @@ export interface NetworkInfo {
adminKeys: string[];
threshold: number;
lastRelayedBlock: number;
lastExpressedBlock: number;
gatewayAddress: string;
gasReceiverAddress: string;
expressServiceAddress: string;
expressProxyDeployerAddress: string;
constAddressDeployerAddress: string;
create3DeployerAddress: string;
tokens: { [key: string]: string };
Expand All @@ -61,6 +60,7 @@ export interface NetworkSetup {
adminKeys?: Wallet[];
threshold?: number;
lastRelayedBlock?: number;
lastExpressedBlock?: number;
}

/*
Expand All @@ -77,12 +77,11 @@ export class Network {
adminWallets: Wallet[];
threshold: number;
lastRelayedBlock: number;
lastExpressedBlock: number;
gateway: AxelarGateway;
gasService: AxelarGasService;
constAddressDeployer: Contract;
create3Deployer: Contract;
expressService: Contract;
expressProxyDeployer: Contract;
isRemote: boolean | undefined;
url: string | undefined;
ganacheProvider: any;
Expand All @@ -100,12 +99,11 @@ export class Network {
this.adminWallets = networkish.adminWallets;
this.threshold = networkish.threshold;
this.lastRelayedBlock = networkish.lastRelayedBlock;
this.lastExpressedBlock = networkish.lastExpressedBlock;
this.gateway = networkish.gateway;
this.gasService = networkish.gasService;
this.constAddressDeployer = networkish.constAddressDeployer;
this.create3Deployer = networkish.create3Deployer;
this.expressService = networkish.expressService;
this.expressProxyDeployer = networkish.expressProxyDeployer;
this.isRemote = networkish.isRemote;
this.url = networkish.url;
this.tokens = networkish.tokens;
Expand Down Expand Up @@ -203,20 +201,6 @@ export class Network {
return this.create3Deployer;
}

async deployExpressServiceContract(): Promise<Contract> {
logger.log(`Deploying the Express Service Contract for ${this.name}... `);
const expressProxyDeployer = await deployContract(this.ownerWallet, GMPExpressProxyDeployer, [this.gateway.address]);
const expressService = await deployContract(this.ownerWallet, GMPExpressService, [
this.gateway.address,
expressProxyDeployer.address,
this.ownerWallet.address,
]);
this.expressService = new Contract(expressService.address, GMPExpressService.abi, this.provider);
this.expressProxyDeployer = new Contract(expressProxyDeployer.address, GMPExpressProxyDeployer.abi, this.provider);
logger.log(`Deployed ExpressService at ${expressService.address}`);
return expressService;
}

async deployToken(name: string, symbol: string, decimals: number, cap: bigint, address: string = ADDRESS_ZERO, alias: string = symbol) {
logger.log(`Deploying ${name} for ${this.name}... `);
const data = arrayify(
Expand Down Expand Up @@ -252,6 +236,7 @@ export class Network {

async giveToken(address: string, alias: string, amount: bigint) {
const symbol = this.tokens[alias] || alias;

const data = arrayify(
defaultAbiCoder.encode(
['uint256', 'bytes32[]', 'string[]', 'bytes[]'],
Expand Down Expand Up @@ -279,10 +264,9 @@ export class Network {
adminKeys: this.adminWallets.map((wallet) => wallet.privateKey),
threshold: this.threshold,
lastRelayedBlock: this.lastRelayedBlock,
lastExpressedBlock: this.lastExpressedBlock,
gatewayAddress: this.gateway.address,
gasReceiverAddress: this.gasService.address,
expressProxyDeployerAddress: this.expressProxyDeployer.address,
expressServiceAddress: this.expressService.address,
constAddressDeployerAddress: this.constAddressDeployer.address,
create3DeployerAddress: this.create3Deployer.address,
tokens: this.tokens,
Expand All @@ -299,14 +283,6 @@ export class Network {
constAddressDeployer: this.constAddressDeployer.address,
create3Deployer: this.create3Deployer.address,
tokens: this.tokens,
GMPExpressService: {
expressOperator: this.ownerWallet.address,
salt: 'GMPExpressService',
address: this.expressService.address,
implementation: this.expressService.address,
deployer: this.ownerWallet.address,
proxyDeployer: this.expressProxyDeployer.address,
},
};
}
}
Expand Down
119 changes: 119 additions & 0 deletions packages/axelar-local-dev/src/__tests__/export.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* eslint-disable @typescript-eslint/no-var-requires */
'use strict';

import chai from 'chai';
import { Wallet } from 'ethers';
import fs from 'fs';
const { expect } = chai;
import { deployContract, setLogger, createAndExport, destroyExported, Network, networks } from '../';
import { AxelarExpressExecutable__factory as AxelarExpressExecutableFactory } from '../types/factories/@axelar-network/axelar-gmp-sdk-solidity/contracts/express/AxelarExpressExecutable__factory';
import { ExpressWithToken__factory as ExpressWithTokenFactory } from '../types/factories/src/contracts/test/ExpressWithToken__factory';
import { ExecutableWithToken__factory as ExecuteWithTokenFactory } from '../types/factories/src/contracts/test/ExecutableWithToken__factory';
import ExpressWithToken from '../artifacts/src/contracts/test/ExpressWithToken.sol/ExpressWithToken.json';
import ExecuteWithToken from '../artifacts/src/contracts/test/ExecutableWithToken.sol/ExecutableWithToken.json';
import { EvmRelayer } from '../relay/EvmRelayer';

setLogger(() => null);

async function deployAndFundUsdc(chain: Network) {
await chain.deployToken('Axelar Wrapped aUSDC', 'aUSDC', 6, BigInt(1e22));
}

describe('createAndExport', () => {
const wallet = Wallet.createRandom();
const chains = ['A', 'B'];
const outputPath = './local.json';
const evmRelayer = new EvmRelayer();
let chain1: Network;
let chain2: Network;
let srcOwner: Wallet;
let destOwner: Wallet;

beforeEach(async () => {
await createAndExport({
accountsToFund: [wallet.address],
chainOutputPath: outputPath,
callback: (chain: Network) => deployAndFundUsdc(chain),
relayers: { evm: evmRelayer },
chains,
relayInterval: 500,
});

chain1 = networks[0];
chain2 = networks[1];
srcOwner = networks[0].ownerWallet;
destOwner = networks[1].ownerWallet;
});

afterEach(async () => {
await destroyExported({ evm: evmRelayer });
});

it('should export a local.json file correctly', async () => {
const data = fs.readFileSync(outputPath, 'utf8');
const chainJson = JSON.parse(data);
// read file and convert to json object
expect(chainJson.length).to.equal(2);
expect(chainJson[0].name).to.equal(chains[0]);
expect(chainJson[1].name).to.equal(chains[1]);

for (const chain of chainJson) {
expect(chain.gateway).to.not.be.undefined;
expect(chain.gasService).to.not.be.undefined;
expect(chain.constAddressDeployer).to.not.be.undefined;
expect(chain.create3Deployer).to.not.be.undefined;
expect(chain.rpc).to.be.not.undefined;
expect(chain.tokens.aUSDC).to.not.be.undefined;
}
});

it('should be able to relay tokens from chain A to chain B', async () => {
const contract1 = await deployContract(srcOwner, ExecuteWithToken, [chain1.gateway.address, chain1.gasService.address]).then(
(contract) => ExecuteWithTokenFactory.connect(contract.address, srcOwner)
);

const contract2 = await deployContract(destOwner, ExecuteWithToken, [chain2.gateway.address, chain2.gasService.address]).then(
(contract) => ExecuteWithTokenFactory.connect(contract.address, destOwner)
);

await contract1.addSibling(chain2.name, contract2.address);

const amount = BigInt(1e18);
await chain1.giveToken(srcOwner.address, 'aUSDC', amount);

const token1 = await chain1.getTokenContract('aUSDC');
await token1.connect(srcOwner).approve(contract1.address, amount);

// print eth balance of owner
await contract1.setAndSend(chain2.name, 'hello', wallet.address, 'aUSDC', amount, { value: BigInt(1e12) });

await new Promise((resolve) => setTimeout(resolve, 3000));

const token2 = await chain2.getTokenContract('aUSDC');
const balance = await token2.balanceOf(wallet.address);
expect(balance.toBigInt()).to.equal(amount);
expect(await contract2.value()).to.equal('hello');
});

it('should be able to call express tokens from chain A to chain B', async () => {
const contract1 = await deployContract(srcOwner, ExpressWithToken, [chain1.gateway.address, chain1.gasService.address]).then(
(contract) => ExpressWithTokenFactory.connect(contract.address, srcOwner)
);
const contract2 = await deployContract(destOwner, ExpressWithToken, [chain2.gateway.address, chain2.gasService.address]).then(
(contract) => AxelarExpressExecutableFactory.connect(contract.address, destOwner)
);

const amount = BigInt(1e18);
await chain1.giveToken(srcOwner.address, 'aUSDC', amount);
const token1 = (await chain1.getTokenContract('aUSDC')).connect(srcOwner);

await token1.approve(contract1.address, amount);
await contract1.sendToMany(chain2.name, contract2.address, [wallet.address], 'aUSDC', amount, { value: BigInt(1e17) });

await new Promise((resolve) => setTimeout(resolve, 3000));

const token2 = await chain2.getTokenContract('aUSDC');
const balance = await token2.balanceOf(wallet.address);
expect(balance.toBigInt()).to.equal(amount);
});
});
1 change: 0 additions & 1 deletion packages/axelar-local-dev/src/__tests__/forking.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ interface NetworkUsdc extends Network {
}

describe.skip("forking", () => {
jest.setTimeout(2000000);

afterEach(async () => {
await stopAll();
Expand Down
4 changes: 1 addition & 3 deletions packages/axelar-local-dev/src/__tests__/network.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import chai from 'chai';
const { expect } = chai;
setLogger(() => null);

jest.setTimeout(300000);

function validateNetwork(network: Network) {
// wallets
Expand All @@ -26,8 +25,6 @@ function validateNetwork(network: Network) {
expect(network.constAddressDeployer).to.not.be.undefined;
expect(network.create3Deployer).to.not.be.undefined;
expect(network.gateway).to.not.be.undefined;
expect(network.expressService).to.not.be.undefined;
expect(network.expressProxyDeployer).to.not.be.undefined;
}

describe('Network', () => {
Expand Down Expand Up @@ -63,6 +60,7 @@ describe('Network', () => {
network = await getNetwork(`http://localhost:${port}`);
validateNetwork(network);
});

it('should deploy a network on a preexisting chain', async () => {
const port = 8600;
const accounts = defaultAccounts(20);
Expand Down
Loading