Skip to content

Commit

Permalink
feat: deploy gas service v6.1 with operators contract on testnet (#46)
Browse files Browse the repository at this point in the history
* feat: v6 deployment improvements

* upgrade to v5.3.1

* address comments

* feat: deploy gas service v6.1 with operators contract on testnet
  • Loading branch information
milapsheth authored Sep 14, 2023
1 parent ba15cb7 commit 8c887a2
Show file tree
Hide file tree
Showing 5 changed files with 244 additions and 69 deletions.
21 changes: 16 additions & 5 deletions evm/deploy-upgradable.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@ function getProxy(wallet, proxyAddress) {
return new Contract(proxyAddress, IUpgradable.abi, wallet);
}

async function getImplementationArgs(contractName, config) {
async function getImplementationArgs(contractName, config, options) {
const contractConfig = config[contractName];

switch (contractName) {
case 'AxelarGasService': {
if (options.args) {
contractConfig.collector = options.args;
}

const collector = contractConfig.collector;

if (!isAddress(collector)) {
throw new Error(`Missing AxelarGasService.collector in the chain info.`);
throw new Error(`Missing AxelarGasService.collector ${collector}.`);
}

return [collector];
Expand Down Expand Up @@ -94,7 +98,7 @@ function getUpgradeArgs(contractName, config) {
* Deploy or upgrade an upgradable contract that's based on the init proxy pattern.
*/
async function deploy(options, chain) {
const { artifactPath, contractName, deployMethod, privateKey, upgrade, verifyEnv, yes } = options;
const { contractName, deployMethod, privateKey, upgrade, verifyEnv, yes } = options;
const verifyOptions = verifyEnv ? { env: verifyEnv, chain: chain.name } : null;

if (deployMethod === 'create3' && (contractName === 'AxelarGasService' || contractName === 'AxelarDepositService')) {
Expand All @@ -107,6 +111,11 @@ async function deploy(options, chain) {
const wallet = new Wallet(privateKey, provider);
await printWalletInfo(wallet);

const artifactPath =
options.artifactPath ||
'@axelar-network/axelar-cgp-solidity/artifacts/contracts/' +
(contractName === 'AxelarGasService' ? 'gas-service/' : 'deposit-service/');

const implementationPath = artifactPath + contractName + '.sol/' + contractName + '.json';
const proxyPath = artifactPath + contractName + 'Proxy.sol/' + contractName + 'Proxy.json';
const implementationJson = require(implementationPath);
Expand All @@ -119,7 +128,7 @@ async function deploy(options, chain) {
}

const contractConfig = contracts[contractName];
const implArgs = await getImplementationArgs(contractName, contracts);
const implArgs = await getImplementationArgs(contractName, contracts, options);
const gasOptions = contractConfig.gasOptions || chain.gasOptions || {};
printInfo(`Implementation args for chain ${chain.name}`, implArgs);
console.log(`Gas override for chain ${chain.name}: ${JSON.stringify(gasOptions)}`);
Expand Down Expand Up @@ -150,6 +159,7 @@ async function deploy(options, chain) {
if (!yes) {
const anwser = readlineSync.question(`Perform an upgrade for ${chain.name}? ${chalk.green('(y/n)')} `);
if (anwser !== 'y') return;
console.log('');
}

await upgradeUpgradable(
Expand Down Expand Up @@ -306,17 +316,18 @@ program.addOption(
.makeOptionMandatory(true)
.env('ENV'),
);
program.addOption(new Option('-a, --artifactPath <artifactPath>', 'artifact path').makeOptionMandatory(true));
program.addOption(new Option('-c, --contractName <contractName>', 'contract name').makeOptionMandatory(true));
program.addOption(new Option('-n, --chainNames <chainNames>', 'chain names').makeOptionMandatory(true));
program.addOption(
new Option('-m, --deployMethod <deployMethod>', 'deployment method').choices(['create', 'create2', 'create3']).default('create2'),
);
program.addOption(new Option('-a, --artifactPath <artifactPath>', 'artifact path'));
program.addOption(new Option('-p, --privateKey <privateKey>', 'private key').makeOptionMandatory(true).env('PRIVATE_KEY'));
program.addOption(new Option('-s, --salt <salt>', 'salt to use for create2 deployment'));
program.addOption(new Option('-u, --upgrade', 'upgrade a deployed contract'));
program.addOption(new Option('-v, --verify', 'verify the deployed contract on the explorer').env('VERIFY'));
program.addOption(new Option('-y, --yes', 'skip deployment prompt confirmation').env('YES'));
program.addOption(new Option('--args <args>', 'customize deployment args'));

program.action((options) => {
main(options);
Expand Down
29 changes: 22 additions & 7 deletions evm/ownership.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ const {
Contract,
} = ethers;
const { Command, Option } = require('commander');
const { printInfo, printWalletInfo, loadConfig } = require('./utils');
const { printInfo, printWalletInfo, loadConfig, saveConfig } = require('./utils');
const readlineSync = require('readline-sync');
const chalk = require('chalk');

const IOwnable = require('@axelar-network/axelar-gmp-sdk-solidity/artifacts/contracts/interfaces/IOwnable.sol/IOwnable.json');

async function processCommand(options, chain) {
const { contractName, address, action, privateKey, newOwner } = options;
const { contractName, address, action, privateKey, newOwner, yes } = options;

const contracts = chain.contracts;
const contractConfig = contracts[contractName];
Expand All @@ -35,18 +38,24 @@ async function processCommand(options, chain) {
const rpc = chain.rpc;
const provider = getDefaultProvider(rpc);

printInfo('Chain', chain.name);
printInfo('Contract name', contractName);

const wallet = new Wallet(privateKey, provider);
await printWalletInfo(wallet);

printInfo('Contract name', contractName);

const ownershipContract = new Contract(ownershipAddress, IOwnable.abi, wallet);

const gasOptions = contractConfig.gasOptions || chain.gasOptions || {};
console.log(`Gas override for chain ${chain.name}: ${JSON.stringify(gasOptions)}`);
printInfo(`Gas override for ${chain.name}`, JSON.stringify(gasOptions));

printInfo('Ownership Action', action);

if (!yes) {
const anwser = readlineSync.question(`Proceed with action on ${chain.name}? ${chalk.green('(y/n)')} `);
if (anwser !== 'y') return;
}

switch (action) {
case 'owner': {
const owner = await ownershipContract.owner();
Expand Down Expand Up @@ -92,6 +101,8 @@ async function processCommand(options, chain) {

printInfo(`New contract owner: ${owner}`);

contractConfig.owner = owner;

break;
}

Expand Down Expand Up @@ -148,6 +159,8 @@ async function processCommand(options, chain) {

printInfo(`New contract owner: ${newOwner}`);

contractConfig.owner = newOwner;

break;
}

Expand All @@ -174,6 +187,7 @@ async function main(options) {

for (const chain of chains) {
await processCommand(options, config.chains[chain.toLowerCase()]);
saveConfig(config, options.env);
}
}

Expand All @@ -191,7 +205,7 @@ program.addOption(

program.addOption(new Option('-p, --privateKey <privateKey>', 'private key').makeOptionMandatory(true).env('PRIVATE_KEY'));
program.addOption(new Option('-c, --contractName <contractName>', 'contract name').makeOptionMandatory(true));
program.addOption(new Option('-n, --chain <chain>', 'chain name').makeOptionMandatory(true));
program.addOption(new Option('-n, --chainNames <chainNames>', 'chain names').makeOptionMandatory(true));
program.addOption(new Option('--address <address>', 'override address').makeOptionMandatory(false));
program.addOption(
new Option('--action <action>', 'ownership action').choices([
Expand All @@ -202,7 +216,8 @@ program.addOption(
'acceptOwnership',
]),
);
program.addOption(new Option('-d, --newOwner <newOwner>', 'new owner address').makeOptionMandatory(false));
program.addOption(new Option('--newOwner <newOwner>', 'new owner address').makeOptionMandatory(false));
program.addOption(new Option('-y, --yes', 'skip deployment prompt confirmation').env('YES'));

program.action((options) => {
main(options);
Expand Down
35 changes: 26 additions & 9 deletions evm/upgradable.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { Contract, ContractFactory } = require('ethers');
const { deployAndInitContractConstant, create3DeployAndInitContract } = require('@axelar-network/axelar-gmp-sdk-solidity');
const IUpgradable = require('@axelar-network/axelar-gmp-sdk-solidity/interfaces/IUpgradable.json');

const { verifyContract, deployCreate, getBytecodeHash, deployContract, printInfo } = require('./utils');
const { verifyContract, deployCreate, getBytecodeHash, deployContract, printInfo, getDeployedAddress, isContract } = require('./utils');

async function deployUpgradable(
wallet,
Expand Down Expand Up @@ -111,15 +111,32 @@ async function upgradeUpgradable(
) {
const proxy = new Contract(proxyAddress, IUpgradable.abi, wallet);

const implementation = await deployContract(
deployMethod,
wallet,
const predictedAddress = await getDeployedAddress(wallet.address, deployMethod, {
...deployOptions,
contractJson,
implementationConstructorArgs,
deployOptions,
gasOptions,
verifyOptions,
);
constructorArgs: implementationConstructorArgs,
provider: wallet.provider,
});

printInfo('Predicted Implementation Address', predictedAddress);
let implementation;

if (await isContract(predictedAddress, wallet.provider)) {
printInfo('New Implementation already deployed', predictedAddress);
implementation = new Contract(predictedAddress, contractJson.abi, wallet);
} else {
implementation = await deployContract(
deployMethod,
wallet,
contractJson,
implementationConstructorArgs,
deployOptions,
gasOptions,
verifyOptions,
);
printInfo('New Implementation', implementation.address);
}

const implementationCodeHash = await getBytecodeHash(implementation, chain);
printInfo('New Implementation Code Hash', implementationCodeHash);

Expand Down
18 changes: 11 additions & 7 deletions evm/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
const {
ContractFactory,
Contract,
provider,
utils: { computeAddress, getContractAddress, keccak256, isAddress, getCreate2Address, defaultAbiCoder },
} = require('ethers');
const https = require('https');
Expand Down Expand Up @@ -332,11 +331,6 @@ const isAddressArray = (arg) => {
return true;
};

const isContract = async (target) => {
const code = await provider.getCode(target);
return code !== '0x';
};

/**
* Determines if a given input is a valid keccak256 hash.
*
Expand Down Expand Up @@ -696,6 +690,16 @@ function wasEventEmitted(receipt, contract, eventName) {
return receipt.logs.some((log) => log.topics[0] === event.topics[0]);
}

const isContract = async (address, provider) => {
try {
const code = await provider.getCode(address);
return code && code !== '0x';
} catch (err) {
console.error('Error:', err);
return false;
}
};

module.exports = {
deployCreate,
deployCreate2,
Expand All @@ -718,7 +722,6 @@ module.exports = {
isNumber,
isNumberArray,
isAddressArray,
isContract,
isKeccak256Hash,
parseArgs,
getProxy,
Expand All @@ -731,4 +734,5 @@ module.exports = {
etaToUnixTimestamp,
getCurrentTimeInSeconds,
wasEventEmitted,
isContract,
};
Loading

0 comments on commit 8c887a2

Please sign in to comment.