diff --git a/.github/workflows/test-sui.yaml b/.github/workflows/test-sui.yaml index 4dd2cf672..07370fdb0 100644 --- a/.github/workflows/test-sui.yaml +++ b/.github/workflows/test-sui.yaml @@ -244,9 +244,16 @@ jobs: echo "transferPayloadHash=$(echo $transferInfo | jq -r .payloadHash)" >> $GITHUB_ENV echo "transferPayload=$(echo $transferInfo | jq -r .payload)" >> $GITHUB_ENV + echo "originTokenId=$(echo $transferInfo | jq -r .tokenId)" >> $GITHUB_ENV echo "deployPayload=$(echo $deploymentInfo | jq -r .payload)" >> $GITHUB_ENV echo "deployPayloadHash=$(echo $deploymentInfo | jq -r .payloadHash)" >> $GITHUB_ENV + - name: ITS Flow Limit Set + run: node sui/its.js set-flow-limits $originTokenId 0 -y + + - name: ITS Flow Limit Remove + run: node sui/its.js set-flow-limits $originTokenId none -y + - name: Setup Trusted Addresses run: | node sui/its.js add-trusted-chains $sourceChain diff --git a/sui/deploy-contract.js b/sui/deploy-contract.js index 58a850697..35bfed434 100644 --- a/sui/deploy-contract.js +++ b/sui/deploy-contract.js @@ -276,9 +276,10 @@ async function postDeployIts(published, keypair, client, config, chain, options) const itsHubAddress = config.axelar.contracts.InterchainTokenService.address; - const [ownerCapObjectId, creatorCapObjectId, upgradeCapObjectId] = getObjectIdsByObjectTypes(published.publishTxn, [ + const [ownerCapObjectId, creatorCapObjectId, operatorCapId, upgradeCapObjectId] = getObjectIdsByObjectTypes(published.publishTxn, [ `${published.packageId}::owner_cap::OwnerCap`, `${published.packageId}::creator_cap::CreatorCap`, + `${published.packageId}::operator_cap::OperatorCap`, `${suiPackageAddress}::package::UpgradeCap`, ]); @@ -305,6 +306,7 @@ async function postDeployIts(published, keypair, client, config, chain, options) InterchainTokenServicev0: InterchainTokenServiceV0ObjectId, ChannelId: channelId, OwnerCap: ownerCapObjectId, + OperatorCap: operatorCapId, UpgradeCap: upgradeCapObjectId, }; diff --git a/sui/its.js b/sui/its.js index 87f9e4617..2bb5538c3 100644 --- a/sui/its.js +++ b/sui/its.js @@ -1,7 +1,8 @@ const { Command } = require('commander'); -const { TxBuilder } = require('@axelar-network/axelar-cgp-sui'); +const { TxBuilder, STD_PACKAGE_ID } = require('@axelar-network/axelar-cgp-sui'); const { loadConfig, saveConfig, getChainConfig } = require('../common/utils'); const { addBaseOptions, addOptionsToCommands, getWallet, printWalletInfo, broadcastFromTxBuilder, saveGeneratedTx } = require('./utils'); +const { bcs } = require('@mysten/sui/bcs'); const SPECIAL_CHAINS_TAGS = { ALL_EVM: 'all-evm', // All EVM chains that have InterchainTokenService deployed @@ -16,6 +17,73 @@ function parseTrustedChains(config, trustedChains) { return trustedChains; } +async function setFlowLimits(keypair, client, config, contracts, args, options) { + let [tokenIds, flowLimits] = args; + + const { InterchainTokenService: itsConfig } = contracts; + + const { OperatorCap, InterchainTokenService } = itsConfig.objects; + + const txBuilder = new TxBuilder(client); + + tokenIds = tokenIds.split(','); + flowLimits = flowLimits.split(','); + + if (tokenIds.length !== flowLimits.length) throw new Error(' and have to have the same length.'); + + for (const i in tokenIds) { + const coinTypeTxBuilder = new TxBuilder(client); + let tokenId = await coinTypeTxBuilder.moveCall({ + target: `${itsConfig.address}::token_id::from_address`, + arguments: [tokenIds[i]], + }); + + await coinTypeTxBuilder.moveCall({ + target: `${itsConfig.address}::interchain_token_service::registered_coin_type`, + arguments: [InterchainTokenService, tokenId], + }); + + const resp = await coinTypeTxBuilder.devInspect(keypair.toSuiAddress()); + const coinType = bcs.String.parse(new Uint8Array(resp.results[1].returnValues[0][0])); + + tokenId = await txBuilder.moveCall({ + target: `${itsConfig.address}::token_id::from_address`, + arguments: [tokenIds[i]], + }); + + let flowLimit; + + if (flowLimits[i] === 'none') { + flowLimit = await txBuilder.moveCall({ + target: `${STD_PACKAGE_ID}::option::none`, + arguments: [], + typeArguments: ['u64'], + }); + } else { + flowLimit = await txBuilder.moveCall({ + target: `${STD_PACKAGE_ID}::option::some`, + arguments: [txBuilder.tx.pure.u64(Number(flowLimits[i]))], + typeArguments: ['u64'], + }); + } + + await txBuilder.moveCall({ + target: `${itsConfig.address}::interchain_token_service::set_flow_limit`, + arguments: [InterchainTokenService, OperatorCap, tokenId, flowLimit], + typeArguments: [coinType], + }); + } + + if (options.offline) { + const tx = txBuilder.tx; + const sender = options.sender || keypair.toSuiAddress(); + tx.setSender(sender); + await saveGeneratedTx(tx, `Set flow limits for ${tokenIds} to ${flowLimits}`, client, options); + } else { + await broadcastFromTxBuilder(txBuilder, keypair, 'Setup Trusted Address', options); + } +} + async function addTrustedChains(keypair, client, config, contracts, args, options) { const [trustedChain] = args; @@ -102,6 +170,15 @@ if (require.main === module) { mainProcessor(removeTrustedChain, options, [trustedChains], processCommand); }); + const setFlowLimitsProgram = new Command() + .name('set-flow-limits') + .command('set-flow-limits ') + .description(`Set flow limits for multiple tokens. and can both be comma separated lists`) + .action((tokenIds, flowLimits, options) => { + mainProcessor(setFlowLimits, options, [tokenIds, flowLimits], processCommand); + }); + + program.addCommand(setFlowLimitsProgram); program.addCommand(addTrustedChainsProgram); program.addCommand(removeTrustedChainsProgram);