Skip to content

Commit

Permalink
feat: supports gas payment for two-way calls (#72)
Browse files Browse the repository at this point in the history
* chore: refactor `executeEvmExecutable` and detect two-ways call

* chore: add typechain support

* feat: use typed contract for AxelarGateway and AxelarGasService

* chore: Wrap gas events into a many-events-to-one-fee-amount class

* chore: remove logs

* chore: support 2-ways for contractCallWithToken

* chore: remove estimateGas

* chore: revert tsconfig change

* chore: add npm-run-all back

* chore: reorder devs

* chore: remove GasReceipt

* chore: delete override gas events

* chore: remove unused import

* 1.4.3

* chore: simplify condition

* 1.4.4-alpha.1

* 1.4.4
  • Loading branch information
npty authored Apr 27, 2023
1 parent c3013da commit 12fa574
Show file tree
Hide file tree
Showing 8 changed files with 3,336 additions and 154 deletions.
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ examples/metamask/abi/**.json
./test.js
./quick.json
local.json
temp.js
temp2.js
src/types

#Hardhat files
cache
Expand Down Expand Up @@ -136,4 +135,7 @@ target/
# Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk
**/*.rs.bk

# Near wasm contract
*.wasm
10 changes: 7 additions & 3 deletions hardhat.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require('hardhat-gas-reporter');
require('solidity-coverage');

require('@typechain/hardhat');
/**
* @type import('hardhat/config').HardhatUserConfig
*/
Expand Down Expand Up @@ -29,9 +29,13 @@ module.exports = {
},
},
paths: {
sources: "./src/contracts",
sources: './src/contracts',
},
mocha: {
timeout: 200000
timeout: 200000,
},
typechain: {
outDir: 'src/types',
target: 'ethers-v5',
},
};
3,202 changes: 3,142 additions & 60 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@axelar-network/axelar-local-dev",
"version": "1.4.2",
"version": "1.4.4",
"description": "",
"main": "dist/index.js",
"scripts": {
Expand Down Expand Up @@ -43,8 +43,7 @@
"fs-extra": "^10.1.0",
"ganache": "^7.1.0",
"lodash": "^4.17.21",
"near-workspaces": "^3.2.2",
"npm-run-all": "^4.1.5"
"near-workspaces": "^3.2.2"
},
"devDependencies": {
"@babel/eslint-parser": "^7.19.1",
Expand All @@ -68,6 +67,10 @@
"solhint": "^3.3.7",
"solidity-coverage": "^0.7.21",
"ts-jest": "^29.0.3",
"@typechain/hardhat": "^6.1.5",
"@typechain/ethers-v5": "^10.2.0",
"npm-run-all": "^4.1.5",
"typechain": "^8.1.1",
"typescript": "^4.7.4"
}
}
21 changes: 11 additions & 10 deletions src/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ import { ethers, Wallet, Contract, providers } from 'ethers';
import { logger } from './utils';
import { getSignedExecuteInput, getRandomID, deployContract } from './utils';
import {
AxelarGateway,
AxelarGatewayProxy,
IAxelarGateway,
Auth,
TokenDeployer,
AxelarGasReceiver,
BurnableMintableCappedERC20,
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';

const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000';
Expand Down Expand Up @@ -76,8 +77,8 @@ export class Network {
adminWallets: Wallet[];
threshold: number;
lastRelayedBlock: number;
gateway: Contract;
gasService: Contract;
gateway: AxelarGateway;
gasService: AxelarGasService;
constAddressDeployer: Contract;
create3Deployer: Contract;
expressService: Contract;
Expand Down Expand Up @@ -122,10 +123,10 @@ export class Network {
[defaultAbiCoder.encode(['address[]', 'uint256[]', 'uint256'], [[this.operatorWallet.address], [1], 1])],
]);
const tokenDeployer = await deployContract(this.ownerWallet, TokenDeployer);
const gateway = await deployContract(this.ownerWallet, AxelarGateway, [auth.address, tokenDeployer.address]);
const gateway = await deployContract(this.ownerWallet, AxelarGatewayFactory, [auth.address, tokenDeployer.address]);
const proxy = await deployContract(this.ownerWallet, AxelarGatewayProxy, [gateway.address, params]);
await (await auth.transferOwnership(proxy.address)).wait();
this.gateway = new Contract(proxy.address, IAxelarGateway.abi, this.provider);
this.gateway = AxelarGatewayFactory.connect(proxy.address, this.provider);
logger.log(`Deployed at ${this.gateway.address}`);
return this.gateway;
}
Expand All @@ -148,7 +149,7 @@ export class Network {
[defaultAbiCoder.encode(['address[]', 'uint256[]', 'uint256'], [[this.operatorWallet.address], [1], 1])],
]);
const tokenDeployer = await deployContract(this.ownerWallet, TokenDeployer);
const gateway = await deployContract(this.ownerWallet, AxelarGateway, [auth.address, tokenDeployer.address]);
const gateway = await deployContract(this.ownerWallet, AxelarGatewayFactory, [auth.address, tokenDeployer.address]);
const implementationCode = await this.provider.getCode(gateway.address);
const implementationCodeHash = keccak256(implementationCode);
for (let i = 0; i < oldThreshold; i++) {
Expand All @@ -160,11 +161,11 @@ export class Network {
}
async deployGasReceiver(): Promise<Contract> {
logger.log(`Deploying the Axelar Gas Receiver for ${this.name}... `);
const gasService = await deployContract(this.ownerWallet, AxelarGasReceiver, [this.ownerWallet.address]);
const gasService = await deployContract(this.ownerWallet, AxelarGasServiceFactory, [this.ownerWallet.address]);
const gasReceiverProxy = await deployContract(this.ownerWallet, AxelarGasReceiverProxy);
await gasReceiverProxy.init(gasService.address, this.ownerWallet.address, '0x');

this.gasService = new Contract(gasReceiverProxy.address, AxelarGasReceiver.abi, this.provider);
this.gasService = AxelarGasServiceFactory.connect(gasReceiverProxy.address, this.provider);
logger.log(`Deployed at ${this.gasService.address}`);
return this.gasService;
}
Expand Down
24 changes: 9 additions & 15 deletions src/networkUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,9 @@ import { ethers, Wallet, Contract, providers, getDefaultProvider } from 'ethers'
import { merge } from 'lodash';
import { defaultAccounts, setJSON, httpGet, logger } from './utils';
import { Network, networks, NetworkOptions, NetworkInfo, NetworkSetup } from './Network';
import {
IAxelarGateway,
IAxelarGasService,
GMPExpressService,
AxelarGateway,
ConstAddressDeployer,
GMPExpressProxyDeployer,
Create3Deployer,
} from './contracts';
import { AxelarGateway__factory as AxelarGatewayFactory } from './types/factories/@axelar-network/axelar-cgp-solidity/contracts/AxelarGateway__factory';
import { AxelarGasService__factory as AxelarGasServiceFactory } from './types/factories/@axelar-network/axelar-cgp-solidity/contracts/gas-service/AxelarGasService__factory';
import { GMPExpressService, ConstAddressDeployer, GMPExpressProxyDeployer, Create3Deployer } from './contracts';

const { keccak256, id, solidityPack, toUtf8Bytes } = ethers.utils;

Expand Down Expand Up @@ -154,8 +148,8 @@ export async function getNetwork(urlOrProvider: string | providers.Provider, inf

chain.constAddressDeployer = new Contract(info.constAddressDeployerAddress, ConstAddressDeployer.abi, chain.provider);
chain.create3Deployer = new Contract(info.create3DeployerAddress, Create3Deployer.abi, chain.provider);
chain.gateway = new Contract(info.gatewayAddress, IAxelarGateway.abi, chain.provider);
chain.gasService = new Contract(info.gasReceiverAddress, IAxelarGasService.abi, chain.provider);
chain.gateway = AxelarGatewayFactory.connect(info.gatewayAddress, chain.provider);
chain.gasService = AxelarGasServiceFactory.connect(info.gasReceiverAddress, chain.provider);
chain.expressService = new Contract(info.expressServiceAddress, GMPExpressService.abi, chain.provider);
chain.expressProxyDeployer = new Contract(info.expressProxyDeployerAddress, GMPExpressProxyDeployer.abi, chain.provider);
//chain.usdc = await chain.getTokenContract('aUSDC');
Expand Down Expand Up @@ -223,12 +217,12 @@ export async function forkNetwork(chainInfo: ChainCloneData, options: NetworkOpt

//This section gets the admin accounts so we can unlock them in our fork to upgrade the gateway to a 'localized' version
const forkProvider = getDefaultProvider(chainInfo.rpc);
const gateway = new Contract(chainInfo.gateway, AxelarGateway.abi, forkProvider);
const gateway = AxelarGatewayFactory.connect(chainInfo.gateway, forkProvider);
const KEY_ADMIN_EPOCH = keccak256(toUtf8Bytes('admin-epoch'));
const adminEpoch = await gateway.getUint(KEY_ADMIN_EPOCH);
const PREFIX_ADMIN_THRESHOLD = keccak256(toUtf8Bytes('admin-threshold'));
const thresholdKey = keccak256(solidityPack(['bytes32', 'uint256'], [PREFIX_ADMIN_THRESHOLD, adminEpoch]));
const oldThreshold = await gateway.getUint(thresholdKey);
const oldThreshold = await gateway.getUint(thresholdKey).then((x) => x.toNumber());
const oldAdminAddresses: string[] = [];
for (let i = 0; i < oldThreshold; i++) {
const PREFIX_ADMIN = keccak256(toUtf8Bytes('admin'));
Expand Down Expand Up @@ -266,9 +260,9 @@ export async function forkNetwork(chainInfo: ChainCloneData, options: NetworkOpt
// Delete the line below and uncomment the line after when we deploy create3Deployer
await chain.deployCreate3Deployer();
//chain.create3Deployer = new Contract(chainInfo.create3Deployer, Create3Deployer.abi, chain.provider);
chain.gateway = new Contract(chainInfo.gateway, AxelarGateway.abi, chain.provider);
chain.gateway = AxelarGatewayFactory.connect(chainInfo.gateway, chain.provider);
await chain._upgradeGateway(oldAdminAddresses, oldThreshold);
chain.gasService = new Contract(chainInfo.AxelarGasService.address, IAxelarGasService.abi, chain.provider);
chain.gasService = AxelarGasServiceFactory.connect(chainInfo.AxelarGasService.address, chain.provider);

chain.tokens = {
uusdc: chain.name === 'Ethereum' ? 'USDC' : 'axlUSDC',
Expand Down
25 changes: 16 additions & 9 deletions src/relay/Command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

import { ethers, Contract } from 'ethers';
import { ethers, Contract, BigNumber, ContractReceipt } from 'ethers';
const { defaultAbiCoder } = ethers.utils;
import { networks } from '../Network';
import { CallContractArgs, CallContractWithTokenArgs, RelayData } from './types';
Expand All @@ -15,14 +15,15 @@ export class Command {
name: string;
data: any[];
encodedData: string;
post: ((options: any) => Promise<void>) | undefined;
post: ((options: any) => Promise<any>) | undefined;

constructor(
commandId: string,
name: string,
data: any[],
dataSignature: string[],
post: ((options: any) => Promise<void>) | undefined = undefined,
chain: string | null = null
post: ((options: any) => Promise<any>) | undefined = undefined,
chain: string | null = null,
) {
this.commandId = commandId;
this.name = name;
Expand All @@ -39,15 +40,16 @@ export class Command {
['string', 'string', 'address', 'bytes32'],
async (options: any) => {
const to = networks.find((chain) => chain.name == args.to);
if (!to) return;
if (!to) return undefined;

const contract = new Contract(args.destinationContractAddress, IAxelarExecutable.abi, to.relayerWallet);
const tx = await contract
const receipt: ContractReceipt = await contract
.execute(commandId, args.from, args.sourceAddress, args.payload, options)
.then((tx: any) => tx.wait());
relayData.callContract[commandId].execution = tx.transactionHash;
relayData.callContract[commandId].execution = receipt.transactionHash;
return receipt;
},
'evm'
'evm',
);
};

Expand All @@ -74,7 +76,9 @@ export class Command {
)
.then((tx: any) => tx.wait());
relayData.callContractWithToken[commandId].execution = receipt.transactionHash;
}
return receipt;
},
'evm'
);
};

Expand All @@ -92,6 +96,7 @@ export class Command {
);

relayData.callContract[commandId].execution = tx.hash;
return tx;
},
'aptos'
);
Expand All @@ -113,6 +118,8 @@ export class Command {
);

relayData.callContract[commandId].execution = tx.transactionReceipt.hash;

return tx;
},
'near'
);
Expand Down
Loading

0 comments on commit 12fa574

Please sign in to comment.