From 2612b2b1a5988df077e57313f5a03da80b2bddab Mon Sep 17 00:00:00 2001 From: blockchainguyy Date: Wed, 22 Nov 2023 20:39:07 +0530 Subject: [PATCH 1/2] add: util function to check passed value is bytes32 array --- evm/utils.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/evm/utils.js b/evm/utils.js index 9bc48067a..13ea514a0 100644 --- a/evm/utils.js +++ b/evm/utils.js @@ -251,6 +251,20 @@ const isAddressArray = (arr) => { return true; }; +const isBytes32Array = (arr) => { + if (!Array.isArray(arr)) { + return false; + } + + for (const item of arr) { + if (typeof item !== 'string' || !item.startsWith('0x') || item.length !== 66) { + return false; + } + } + + return true; +}; + const getCurrentTimeInSeconds = () => { const now = new Date(); const currentTimeInSecs = Math.floor(now.getTime() / 1000); @@ -971,4 +985,5 @@ module.exports = { mainProcessor, getContractPath, getContractJSON, + isBytes32Array, }; From 30444714f6e0f6e14eb83657cb3cc436e84e05fd Mon Sep 17 00:00:00 2001 From: blockchainguyy Date: Wed, 22 Nov 2023 20:40:04 +0530 Subject: [PATCH 2/2] add: option to set flow limit in its including offline signing --- evm/multisig.js | 61 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/evm/multisig.js b/evm/multisig.js index dbdf5a705..f8464fa09 100644 --- a/evm/multisig.js +++ b/evm/multisig.js @@ -22,11 +22,15 @@ const { mainProcessor, isValidDecimal, prompt, + isBytes32Array, } = require('./utils'); const { addBaseOptions } = require('./cli-utils'); const IMultisig = require('@axelar-network/axelar-gmp-sdk-solidity/interfaces/IMultisig.json'); const IGateway = require('@axelar-network/axelar-gmp-sdk-solidity/interfaces/IAxelarGateway.json'); const IGovernance = require('@axelar-network/axelar-gmp-sdk-solidity/interfaces/IAxelarServiceGovernance.json'); +const IInterchainTokenService = require('@axelar-network/interchain-token-service/interfaces/IInterchainTokenService.json'); +const ITokenManager = require('@axelar-network/interchain-token-service/interfaces/ITokenManager.json'); +const IOperatable = require('@axelar-network/interchain-token-service/interfaces/IOperatable.json'); const { parseEther } = require('ethers/lib/utils'); const { getWallet, signTransaction, storeSignedTx } = require('./sign-utils'); @@ -83,6 +87,7 @@ async function processCommand(_, chain, options) { address, action, symbols, + tokenIds, limits, mintLimiter, recipient, @@ -288,6 +293,57 @@ async function processCommand(_, chain, options) { tx = await governanceContract.populateTransaction.executeMultisigProposal(target, calldata, nativeValue); break; } + + case 'setFlowLimits': { + const tokenIdsArray = JSON.parse(tokenIds); + const limitsArray = JSON.parse(limits); + + if (!isBytes32Array(tokenIdsArray)) { + throw new Error(`Invalid token symbols: ${tokenIds}`); + } + + if (!isNumberArray(limitsArray)) { + throw new Error(`Invalid token limits: ${limits}`); + } + + if (tokenIdsArray.length !== limitsArray.length) { + throw new Error('Token ids and token flow limits length mismatch'); + } + + const multisigTarget = chain.contracts.InterchainTokenService?.address; + + if (!isValidAddress(multisigTarget)) { + throw new Error(`Missing InterchainTokenService address in the chain info.`); + } + + const its = new Contract(multisigTarget, IInterchainTokenService.abi, wallet); + const multisigCalldata = its.interface.encodeFunctionData('setFlowLimits', [tokenIdsArray, limitsArray]); + + printInfo('Token Ids', tokenIdsArray); + printInfo('FLow limit values', limitsArray); + + if (!offline) { + await preExecutionChecks(multisigContract, action, wallet, multisigTarget, multisigCalldata, 0, yes); + const operatable = new Contract(multisigTarget, IOperatable.abi, wallet); + const hasOperatorRole = await operatable.isOperator(wallet.address); + + if (!hasOperatorRole) { + throw new Error('Missing Operator role for the used wallet address.'); + } + + // loop over each token + for (let i = 0; i < tokenIdsArray.length; ++i) { + const tokenManagerAddress = await its.validTokenManagerAddress(tokenIdsArray[i]); + const tokenManager = new Contract(tokenManagerAddress, ITokenManager.abi, wallet); + const currentFlowLimit = await tokenManager.flowLimit(tokenIdsArray[i]); + printInfo(`TokenManager address`, tokenManagerAddress); + printInfo(`TokenManager current flowLimit`, currentFlowLimit); + } + } + + tx = await multisigContract.populateTransaction.executeContract(multisigTarget, multisigCalldata, 0, gasOptions); + break; + } } const { baseTx, signedTx } = await signTransaction(wallet, chain, tx, options); @@ -324,7 +380,7 @@ if (require.main === module) { program.addOption(new Option('-c, --contractName ', 'contract name').default('Multisig').makeOptionMandatory(false)); program.addOption( new Option('--action ', 'multisig action') - .choices(['signers', 'setTokenMintLimits', 'transferMintLimiter', 'withdraw', 'executeMultisigProposal']) + .choices(['signers', 'setTokenMintLimits', 'transferMintLimiter', 'withdraw', 'executeMultisigProposal', 'setFlowLimits']) .makeOptionMandatory(true), ); program.addOption(new Option('--offline', 'run script in offline mode')); @@ -348,6 +404,9 @@ if (require.main === module) { new Option('--nativeValue ', 'execute multisig proposal nativeValue').makeOptionMandatory(false).default(0), ); + // option for setFlowLimit in ITS + program.addOption(new Option('--tokenIds ', 'token ids')); + program.action((options) => { main(options); });