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: add option to set flow limit through its in multisig script [AXE-2678] #120

Merged
merged 7 commits into from
Dec 13, 2023
61 changes: 60 additions & 1 deletion evm/multisig.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ const {
mainProcessor,
isValidDecimal,
prompt,
isBytes32Array,
getGasOptions,
} = 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');

Expand Down Expand Up @@ -82,6 +86,7 @@ async function processCommand(_, chain, options) {
address,
action,
symbols,
tokenIds,
limits,
mintLimiter,
recipient,
Expand Down Expand Up @@ -286,6 +291,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);
Expand Down Expand Up @@ -322,7 +378,7 @@ if (require.main === module) {
program.addOption(new Option('-c, --contractName <contractName>', 'contract name').default('Multisig').makeOptionMandatory(false));
program.addOption(
new Option('--action <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'));
Expand All @@ -346,6 +402,9 @@ if (require.main === module) {
new Option('--nativeValue <nativeValue>', 'execute multisig proposal nativeValue').makeOptionMandatory(false).default(0),
);

// option for setFlowLimit in ITS
program.addOption(new Option('--tokenIds <tokenIds>', 'token ids'));

program.action((options) => {
main(options);
});
Expand Down
15 changes: 15 additions & 0 deletions evm/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,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);
Expand Down Expand Up @@ -1035,6 +1049,7 @@ module.exports = {
mainProcessor,
getContractPath,
getContractJSON,
isBytes32Array,
getGasOptions,
getSaltFromKey,
};
Loading