From 2e2c7139e5572606fd4d8e3a3fca0762f91d879f Mon Sep 17 00:00:00 2001 From: eguajardo Date: Tue, 14 Jan 2025 09:08:09 -0600 Subject: [PATCH] feat(cosmwasm): add subcommand for migration through admin account (#495) --- cosmwasm/README.md | 7 ++++--- cosmwasm/deploy-contract.js | 31 +++++++++++++++++++++++++++++++ cosmwasm/utils.js | 18 +++++++++++++++--- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/cosmwasm/README.md b/cosmwasm/README.md index 1e1cfeb7..3cbd5c3e 100644 --- a/cosmwasm/README.md +++ b/cosmwasm/README.md @@ -112,7 +112,7 @@ This folder contains deployment scripts for cosmwasm contracts needed for amplif Deploy each contract. Chain name should match the key of an object in the `chains` section of the config. Chain name should be omitted for contracts that are not chain specific. - `node deploy-contract.js [upload|instantiate|upload-instantiate] -m [mnemonic] -a [path to contract artifacts] -c [contract name] -e [environment] -n ` + `node deploy-contract.js [upload|instantiate|upload-instantiate|migrate] -m [mnemonic] -a [path to contract artifacts] -c [contract name] -e [environment] -n ` Available subcommands: @@ -126,6 +126,8 @@ Available subcommands: - `upload-instantiate`: Both uploads and then instantiates a contract using the code Id that was just created. It doesn't accept `--codeId` nor `--fetchCodeId` options +- `migrate`: Migrates a contract using a new codeId, which is retrieved the same way as `instantiate` subcommand. The migrate message must be provided using the `--msg` option. + Some of the contracts depend on each other and need to be deployed in a specific order. Note the connection router and axelarnet gateway each need to know the other's address, so you need to pass `--instantiate2`, and upload both contract before instatiating them. Example deployments: @@ -146,9 +148,8 @@ Example deployments: ### Constant Address Deployment To deploy with a constant address using instantiate2, pass the `--instantiate2` flag. -To upload the contract and compute the expected address without instantiating, pass `--instantiate2` and `-u`. This will write the contract address and the code id to the config file. +To upload the contract and compute the expected address without instantiating, pass `--instantiate2` while using the `upload` subcommand. This will write the contract address and the code id to the config file. A salt can be passed with `-s`. If no salt is passed but a salt is needed for constant address deployment, the contract name will be used as a salt. -Pass `-r` to skip the upload step, and reuse the previous code id (specified in the config). ### Deploying through governance proposals diff --git a/cosmwasm/deploy-contract.js b/cosmwasm/deploy-contract.js index 0d4de1a0..05f5251b 100644 --- a/cosmwasm/deploy-contract.js +++ b/cosmwasm/deploy-contract.js @@ -16,6 +16,7 @@ const { getCodeId, uploadContract, instantiateContract, + migrateContract, } = require('./utils'); const { Command } = require('commander'); @@ -69,6 +70,23 @@ const uploadInstantiate = async (client, wallet, config, options) => { await instantiate(client, wallet, config, options); }; +const migrate = async (client, wallet, config, options) => { + const { yes } = options; + const { contractConfig } = getAmplifierContractConfig(config, options); + + const codeId = await getCodeId(client, config, options); + printInfo('Using code id', codeId); + + if (prompt(`Proceed with contract migration on axelar?`, yes)) { + return; + } + + contractConfig.codeId = codeId; + + const { transactionHash } = await migrateContract(client, wallet, config, options); + printInfo('Migration completed. Transaction hash', transactionHash); +}; + const mainProcessor = async (processor, options) => { const { env } = options; const config = loadConfig(env); @@ -127,6 +145,19 @@ const programHandler = () => { instantiate2Options: true, }); + const migrateCmd = program + .command('migrate') + .description('Migrate contract') + .action((options) => { + mainProcessor(migrate, options); + }); + addAmplifierOptions(migrateCmd, { + contractOptions: true, + migrateOptions: true, + codeId: true, + fetchCodeId: true, + }); + program.parse(); }; diff --git a/cosmwasm/utils.js b/cosmwasm/utils.js index 2da36cc7..06a6a7cd 100644 --- a/cosmwasm/utils.js +++ b/cosmwasm/utils.js @@ -137,14 +137,12 @@ const uploadContract = async (client, wallet, config, options) => { const uploadFee = gasLimit === 'auto' ? 'auto' : calculateFee(gasLimit, GasPrice.fromString(gasPrice)); // uploading through stargate doesn't support defining instantiate permissions - return await client.upload(account.address, wasm, uploadFee); + return client.upload(account.address, wasm, uploadFee); }; const instantiateContract = async (client, wallet, initMsg, config, options) => { const { contractName, salt, instantiate2, chainName, admin } = options; - const [account] = await wallet.getAccounts(); - const { contractConfig } = getAmplifierContractConfig(config, options); const { @@ -171,6 +169,19 @@ const instantiateContract = async (client, wallet, initMsg, config, options) => return contractAddress; }; +const migrateContract = async (client, wallet, config, options) => { + const { msg } = options; + const [account] = await wallet.getAccounts(); + const { contractConfig } = getAmplifierContractConfig(config, options); + + const { + axelar: { gasPrice, gasLimit }, + } = config; + const migrateFee = gasLimit === 'auto' ? 'auto' : calculateFee(gasLimit, GasPrice.fromString(gasPrice)); + + return client.migrate(account.address, contractConfig.address, contractConfig.codeId, JSON.parse(msg), migrateFee); +}; + const validateAddress = (address) => { return isString(address) && isValidCosmosAddress(address); }; @@ -887,6 +898,7 @@ module.exports = { getCodeId, uploadContract, instantiateContract, + migrateContract, fetchCodeIdFromCodeHash, fetchCodeIdFromContract, addDefaultInstantiateAddresses,