diff --git a/.github/workflows/test-sui.yaml b/.github/workflows/test-sui.yaml index 35a3c3e0e..9bdef97fa 100644 --- a/.github/workflows/test-sui.yaml +++ b/.github/workflows/test-sui.yaml @@ -67,6 +67,8 @@ jobs: SUI_ADDRESS=$(sui keytool export --key-identity wallet --json | jq .key.suiAddress | sed 's/"//g') echo "SUI_PRIVATE_KEY=${SUI_PRIVATE_KEY}" >> $GITHUB_ENV echo "SUI_ADDRESS=${SUI_ADDRESS}" >> $GITHUB_ENV + echo "ITS_HUB_CHAIN_NAME=axelar" >> $GITHUB_ENV + echo "ITS_HUB_ADDRESS=hub_address" >> $GITHUB_ENV - name: Spin up Sui Network # sui-test-validator will be deprecated in the future. @@ -89,20 +91,27 @@ jobs: - name: Prepare local.json run: | echo '{ - "chains": { - "sui": { - "name": "Sui", - "axelarId": "sui", - "networkType": "localnet", - "chainType": "sui", - "tokenSymbol": "SUI", - "rpc": "http://127.0.0.1:9000", - "faucetUrl": "http://127.0.0.1:9123", - "contracts": { - "AxelarGateway": {} - } - } + "chains": { + "sui": { + "name": "Sui", + "axelarId": "sui", + "networkType": "localnet", + "chainType": "sui", + "tokenSymbol": "SUI", + "rpc": "http://127.0.0.1:9000", + "faucetUrl": "http://127.0.0.1:9123", + "contracts": { + "AxelarGateway": {} + } } + }, + "axelar": { + "contracts": { + "InterchainTokenService": { + "address": "${{ env.ITS_HUB_ADDRESS }}" + } + } + } }' > ./axelar-chains-config/info/local.json # Create .env file with default hardhat private key that's prefunded @@ -142,8 +151,8 @@ jobs: - name: Deploy ABI run: node sui/deploy-contract deploy Abi - - name: Deploy ITS - run: node sui/deploy-contract deploy ITS + - name: Deploy InterchainTokenService + run: node sui/deploy-contract deploy InterchainTokenService -y - name: Deploy Example run: node sui/deploy-contract deploy Example @@ -197,7 +206,7 @@ jobs: echo "emptyTokenName=Empty" >> $GITHUB_ENV echo "emptyTokenDecimals=6" >> $GITHUB_ENV config=$(cat axelar-chains-config/info/local.json) - echo "channelId=$(echo $config | jq -r '.chains.sui.contracts.ITS.objects.ChannelId')" >> $GITHUB_ENV + echo "channelId=$(echo $config | jq -r '.chains.sui.contracts.InterchainTokenService.objects.ChannelId')" >> $GITHUB_ENV echo "destinationContractAddress=$(echo $config | jq -r '.chains.sui.contracts.Example.objects.ItsChannelId')" >> $GITHUB_ENV - name: Deploy Test Tokens @@ -206,8 +215,8 @@ jobs: node sui/its-example deploy-token ${{ env.emptyTokenSymbol }} ${{ env.emptyTokenName }} ${{ env.emptyTokenDecimals }} # Prepare additional parameters for the example: - transferInfo=$(node sui/its-example.js print-receive-transfer ${{ env.symbol }} ${{ env.sourceAddress }} ${{ env.amount }}) - deploymentInfo=$(node sui/its-example.js print-receive-deployment ${{ env.emptyTokenName }} ${{ env.emptyTokenSymbol }} ${{ env.emptyTokenDecimals }}) + transferInfo=$(node sui/its-example.js print-receive-transfer ${{ env.sourceChain }} ${{ env.symbol }} ${{ env.sourceAddress }} ${{ env.amount }}) + deploymentInfo=$(node sui/its-example.js print-receive-deployment ${{ env.sourceChain }} ${{ env.emptyTokenName }} ${{ env.emptyTokenSymbol }} ${{ env.emptyTokenDecimals }}) echo "transferPayloadHash=$(echo $transferInfo | jq -r .payloadHash)" >> $GITHUB_ENV echo "transferPayload=$(echo $transferInfo | jq -r .payload)" >> $GITHUB_ENV @@ -216,7 +225,7 @@ jobs: - name: Setup Trusted Addresses run: | - node sui/its.js setup-trusted-address $sourceChain $sourceAddress + node sui/its.js add-trusted-chains $sourceChain - name: Send Token to another chain run: | @@ -224,8 +233,8 @@ jobs: - name: Receive Token from another chain run: | - node sui/gateway.js approve --proof wallet $sourceChain $transferMessageId $sourceAddress $channelId $transferPayloadHash - node sui/its-example receive-token $sourceChain $transferMessageId $sourceAddress $symbol $transferPayload + node sui/gateway.js approve --proof wallet ${{ env.ITS_HUB_CHAIN_NAME }} $transferMessageId ${{ env.ITS_HUB_ADDRESS }} $channelId $transferPayloadHash + node sui/its-example receive-token ${{ env.ITS_HUB_CHAIN_NAME }} $transferMessageId ${{ env.ITS_HUB_ADDRESS }} $symbol $transferPayload - name: Send Token Deployment to another chain run: | @@ -233,8 +242,8 @@ jobs: - name: Receive Token Deployment from another chain run: | - node sui/gateway.js approve --proof wallet $sourceChain $deployMessageId $sourceAddress $channelId $deployPayloadHash - node sui/its-example receive-deployment $sourceChain $deployMessageId $sourceAddress $emptyTokenSymbol $deployPayload + node sui/gateway.js approve --proof wallet ${{ env.ITS_HUB_CHAIN_NAME }} $deployMessageId ${{ env.ITS_HUB_ADDRESS }} $channelId $deployPayloadHash + node sui/its-example receive-deployment ${{ env.ITS_HUB_CHAIN_NAME }} $deployMessageId ${{ env.ITS_HUB_ADDRESS }} $emptyTokenSymbol $deployPayload ###### Command: Operators ###### diff --git a/common/utils.js b/common/utils.js index 8fa77a696..71cf5c8f0 100644 --- a/common/utils.js +++ b/common/utils.js @@ -441,10 +441,11 @@ const getMultisigProof = async (config, chain, multisigSessionId) => { const calculateDomainSeparator = (chain, router, network) => keccak256(Buffer.from(`${chain}${router}${network}`)); const getItsEdgeContract = (chainConfig) => { - const itsEdgeContract = chainConfig.contracts.InterchainTokenService?.address || chainConfig.contracts.ITS?.objects?.ChannelId; + const itsEdgeContract = + chainConfig.contracts.InterchainTokenService?.address || chainConfig.contracts.InterchainTokenService?.objects?.ChannelId; if (!itsEdgeContract) { - throw new Error(`Missing ITS edge contract for chain ${chainConfig.name}`); + throw new Error(`Missing InterchainTokenService edge contract for chain ${chainConfig.name}`); } return itsEdgeContract; diff --git a/cosmwasm/submit-proposal.js b/cosmwasm/submit-proposal.js index d959a8223..c23bc87ae 100644 --- a/cosmwasm/submit-proposal.js +++ b/cosmwasm/submit-proposal.js @@ -293,8 +293,8 @@ const programHandler = () => { const registerItsChainCmd = program .command('its-hub-register-chains') - .description('Submit an execute wasm contract proposal to register an ITS chain') - .argument('', 'list of chains to register on ITS hub') + .description('Submit an execute wasm contract proposal to register an InterchainTokenService chain') + .argument('', 'list of chains to register on InterchainTokenService hub') .action((chains, options) => { options.chains = chains; mainProcessor(registerItsChain, options); diff --git a/package-lock.json b/package-lock.json index 1340d81a9..fa7983235 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "@axelar-network/axelar-cgp-solidity": "6.4.0", - "@axelar-network/axelar-cgp-sui": "1.0.3", + "@axelar-network/axelar-cgp-sui": "0.0.0-snapshot.02915b7", "@axelar-network/axelar-gmp-sdk-solidity": "6.0.4", "@axelar-network/interchain-token-service": "2.1.0", "@cosmjs/cosmwasm-stargate": "^0.32.1", @@ -145,9 +145,9 @@ } }, "node_modules/@axelar-network/axelar-cgp-sui": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@axelar-network/axelar-cgp-sui/-/axelar-cgp-sui-1.0.3.tgz", - "integrity": "sha512-JlKaJ0tWtndtx/VLNIcEeKVYPaHgEEhVyeL7vBn695cXKlc9moTkxwmMNvAr3rhXMN6GbyeG8GXx62Rx7QbpSw==", + "version": "0.0.0-snapshot.02915b7", + "resolved": "https://registry.npmjs.org/@axelar-network/axelar-cgp-sui/-/axelar-cgp-sui-0.0.0-snapshot.02915b7.tgz", + "integrity": "sha512-tinW30ThbIx64KCY+/BuQhtFgkxgTVPR2Sx1idBzREXJ8HogZ02j4RdJR6DiP5UVQB0OxrGuQ/WRGsfzUImwKg==", "dependencies": { "@cosmjs/cosmwasm-stargate": "^0.32.2", "@mysten/sui": "^1.3.0", diff --git a/package.json b/package.json index eb84d1f21..561f1633c 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "homepage": "https://github.com/axelarnetwork/axelar-contract-deployments#readme", "dependencies": { "@axelar-network/axelar-cgp-solidity": "6.4.0", - "@axelar-network/axelar-cgp-sui": "1.0.3", + "@axelar-network/axelar-cgp-sui": "0.0.0-snapshot.02915b7", "@axelar-network/axelar-gmp-sdk-solidity": "6.0.4", "@axelar-network/interchain-token-service": "2.1.0", "@cosmjs/cosmwasm-stargate": "^0.32.1", diff --git a/stellar/its.js b/stellar/its.js index 22613bdb5..ed1cfc34d 100644 --- a/stellar/its.js +++ b/stellar/its.js @@ -136,14 +136,14 @@ if (require.main === module) { program .command('set-trusted-chain ') - .description('set a trusted ITS chain') + .description('set a trusted InterchainTokenService chain') .action((chainName, options) => { mainProcessor(setTrustedChain, chainName, options); }); program .command('remove-trusted-chain ') - .description('remove a trusted ITS chain') + .description('remove a trusted InterchainTokenService chain') .action((chainName, options) => { mainProcessor(removeTrustedChain, chainName, options); }); diff --git a/sui/deploy-contract.js b/sui/deploy-contract.js index 8705ca4fb..a1b7beaa0 100644 --- a/sui/deploy-contract.js +++ b/sui/deploy-contract.js @@ -48,7 +48,7 @@ const PACKAGE_DIRS = [ 'operators', 'abi', 'governance', - 'its', + 'interchain_token_service', 'squid', 'interchain_token', ]; @@ -66,7 +66,7 @@ const PACKAGE_CONFIGS = { GasService: postDeployGasService, Example: postDeployExample, Operators: postDeployOperators, - ITS: postDeployIts, + InterchainTokenService: postDeployIts, Squid: postDeploySquid, Utils: postDeployUtils, }, @@ -136,8 +136,8 @@ async function postDeployExample(published, keypair, client, config, chain, opti // GMP Example Params const [gmpSingletonObjectId] = getObjectIdsByObjectTypes(published.publishTxn, [`${published.packageId}::gmp::Singleton`]); - // ITS Example Params - const itsObjectId = chain.contracts.ITS?.objects?.ITS; + // InterchainTokenService Example Params + const itsObjectId = chain.contracts.InterchainTokenService?.objects?.InterchainTokenService; const [itsSingletonObjectId] = getObjectIdsByObjectTypes(published.publishTxn, [`${published.packageId}::its::Singleton`]); const tx = new Transaction(); @@ -246,27 +246,43 @@ async function postDeployAxelarGateway(published, keypair, client, config, chain async function postDeployIts(published, keypair, client, config, chain, options) { const relayerDiscovery = chain.contracts.RelayerDiscovery?.objects?.RelayerDiscovery; - const [itsObjectId, itsv0ObjectId, ownerCapObjectId, upgradeCapObjectId] = getObjectIdsByObjectTypes(published.publishTxn, [ - `${published.packageId}::its::ITS`, - `${published.packageId}::its_v0::ITS_v0`, + const { chainName } = options; + + const itsHubAddress = config.axelar.contracts.InterchainTokenService.address; + + const [ownerCapObjectId, creatorCapObjectId, upgradeCapObjectId] = getObjectIdsByObjectTypes(published.publishTxn, [ `${published.packageId}::owner_cap::OwnerCap`, + `${published.packageId}::creator_cap::CreatorCap`, `${suiPackageAddress}::package::UpgradeCap`, ]); - const channelId = await getItsChannelId(client, itsv0ObjectId); + let tx = new Transaction(); + tx.moveCall({ + target: `${published.packageId}::interchain_token_service::setup`, + arguments: [tx.object(creatorCapObjectId), tx.pure.string(chainName), tx.pure.string(itsHubAddress)], + }); + + const setupReceipt = await broadcast(client, keypair, tx, 'Setup', options); - chain.contracts.ITS.objects = { - ITS: itsObjectId, - ITSv0: itsv0ObjectId, + const [InterchainTokenServiceObjectId, InterchainTokenServiceV0ObjectId] = getObjectIdsByObjectTypes(setupReceipt, [ + `${published.packageId}::interchain_token_service::InterchainTokenService`, + `${published.packageId}::interchain_token_service_v0::InterchainTokenService_v0`, + ]); + await new Promise((resolve) => setTimeout(resolve, 2000)); + const channelId = await getItsChannelId(client, InterchainTokenServiceV0ObjectId); + + chain.contracts.InterchainTokenService.objects = { + InterchainTokenService: InterchainTokenServiceObjectId, + InterchainTokenServicev0: InterchainTokenServiceV0ObjectId, ChannelId: channelId, OwnerCap: ownerCapObjectId, UpgradeCap: upgradeCapObjectId, }; - const tx = new Transaction(); + tx = new Transaction(); tx.moveCall({ target: `${published.packageId}::discovery::register_transaction`, - arguments: [tx.object(itsObjectId), tx.object(relayerDiscovery)], + arguments: [tx.object(InterchainTokenServiceObjectId), tx.object(relayerDiscovery)], }); await broadcast(client, keypair, tx, 'Registered Transaction', options); @@ -285,7 +301,11 @@ async function postDeploySquid(published, keypair, client, config, chain, option const tx = new Transaction(); tx.moveCall({ target: `${published.packageId}::discovery::register_transaction`, - arguments: [tx.object(squidObjectId), tx.object(chain.contracts.ITS.objects.ITS), tx.object(relayerDiscovery)], + arguments: [ + tx.object(squidObjectId), + tx.object(chain.contracts.InterchainTokenService.objects.InterchainTokenService), + tx.object(relayerDiscovery), + ], }); await broadcast(client, keypair, tx, 'Registered Transaction', options); diff --git a/sui/gateway.js b/sui/gateway.js index 2811bbfaf..97f64a165 100644 --- a/sui/gateway.js +++ b/sui/gateway.js @@ -153,6 +153,7 @@ async function approve(keypair, client, config, chain, contractConfig, args, opt const packageId = contractConfig.address; const [sourceChain, messageId, sourceAddress, destinationId, payloadHash] = args; + console.log([sourceChain, messageId, sourceAddress, destinationId, payloadHash]); const encodedMessages = bcs .vector(bcsStructs.gateway.Message) .serialize([ diff --git a/sui/its-example.js b/sui/its-example.js index 69cc8be84..89097030a 100644 --- a/sui/its-example.js +++ b/sui/its-example.js @@ -12,9 +12,9 @@ const { broadcastFromTxBuilder, moveDir, broadcastExecuteApprovedMessage, - checkTrustedAddresses, parseDiscoveryInfo, parseGatewayInfo, + checkTrustedAddresses, } = require('./utils'); const { ethers } = require('hardhat'); const { @@ -24,14 +24,14 @@ const { async function sendToken(keypair, client, contracts, args, options) { const [symbol, destinationChain, destinationAddress, feeAmount, amount] = args; - const { Example, GasService, AxelarGateway, ITS } = contracts; + const { Example, GasService, AxelarGateway, InterchainTokenService } = contracts; const ItsToken = contracts[symbol.toUpperCase()]; if (!ItsToken) { throw new Error(`Token ${symbol} not found. Deploy it first with 'node sui/its-example.js deploy-token' command`); } - checkTrustedAddresses(ITS.trustedAddresses, destinationChain); + await checkTrustedAddresses(destinationChain); const decimals = ItsToken.decimals; @@ -41,7 +41,7 @@ async function sendToken(keypair, client, contracts, args, options) { const objectIds = { singleton: Example.objects.ItsSingleton, - its: ITS.objects.ITS, + its: InterchainTokenService.objects.InterchainTokenService, gateway: AxelarGateway.objects.Gateway, gasService: GasService.objects.GasService, }; @@ -49,11 +49,10 @@ async function sendToken(keypair, client, contracts, args, options) { const txBuilder = new TxBuilder(client); const tx = txBuilder.tx; - const gas = tx.splitCoins(tx.gas, [unitFeeAmount]); const TokenId = await txBuilder.moveCall({ - target: `${ITS.address}::token_id::from_u256`, + target: `${InterchainTokenService.address}::token_id::from_u256`, arguments: [ItsToken.objects.TokenId], }); @@ -87,12 +86,12 @@ async function sendToken(keypair, client, contracts, args, options) { } async function sendDeployment(keypair, client, contracts, args, options) { - const { AxelarGateway, GasService, ITS, Example } = contracts; + const { AxelarGateway, GasService, InterchainTokenService, Example } = contracts; const [symbol, destinationChain, feeAmount] = args; const Token = contracts[symbol.toUpperCase()]; const feeUnitAmount = getUnitAmount(feeAmount); - checkTrustedAddresses(ITS.trustedAddresses, destinationChain); + await checkTrustedAddresses(destinationChain); const txBuilder = new TxBuilder(client); @@ -100,14 +99,14 @@ async function sendDeployment(keypair, client, contracts, args, options) { const gas = tx.splitCoins(tx.gas, [feeUnitAmount]); const TokenId = await txBuilder.moveCall({ - target: `${ITS.address}::token_id::from_u256`, + target: `${InterchainTokenService.address}::token_id::from_u256`, arguments: [Token.objects.TokenId], }); await txBuilder.moveCall({ target: `${Example.address}::its::deploy_remote_interchain_token`, arguments: [ - ITS.objects.ITS, + InterchainTokenService.objects.InterchainTokenService, AxelarGateway.objects.Gateway, GasService.objects.GasService, destinationChain, @@ -123,11 +122,9 @@ async function sendDeployment(keypair, client, contracts, args, options) { } async function handleReceivedMessage(keypair, client, contracts, args, options, actionName) { - const { ITS } = contracts; + const { InterchainTokenService } = contracts; const [sourceChain, messageId, sourceAddress, tokenSymbol, payload] = args; - checkTrustedAddresses(ITS.trustedAddresses, sourceChain); - // Prepare Object Ids const symbol = tokenSymbol.toUpperCase(); @@ -141,7 +138,7 @@ async function handleReceivedMessage(keypair, client, contracts, args, options, source_chain: sourceChain, message_id: messageId, source_address: sourceAddress, - destination_id: ITS.objects.ChannelId, + destination_id: InterchainTokenService.objects.ChannelId, payload, }; @@ -186,8 +183,8 @@ async function deployToken(keypair, client, contracts, args, options) { const [TreasuryCap, Metadata] = getObjectIdsByObjectTypes(publishTxn, [`TreasuryCap<${tokenType}>`, `Metadata<${tokenType}>`]); - // Register Token in ITS - const { Example, ITS } = contracts; + // Register Token in InterchainTokenService + const { Example, InterchainTokenService } = contracts; let tokenId; const postDeployTxBuilder = new TxBuilder(client); @@ -195,13 +192,13 @@ async function deployToken(keypair, client, contracts, args, options) { if (options.origin) { await postDeployTxBuilder.moveCall({ target: `${Example.address}::its::register_coin`, - arguments: [ITS.objects.ITS, Metadata], + arguments: [InterchainTokenService.objects.InterchainTokenService, Metadata], typeArguments: [tokenType], }); const result = await broadcastFromTxBuilder( postDeployTxBuilder, keypair, - `Setup ${symbol} as an origin in ITS successfully`, + `Setup ${symbol} as an origin in InterchainTokenService successfully`, options, { showEvents: true, @@ -210,13 +207,19 @@ async function deployToken(keypair, client, contracts, args, options) { tokenId = result.events[0].parsedJson.token_id.id; } else { await postDeployTxBuilder.moveCall({ - target: `${ITS.address}::its::give_unregistered_coin`, - arguments: [ITS.objects.ITS, TreasuryCap, Metadata], + target: `${InterchainTokenService.address}::interchain_token_service::give_unregistered_coin`, + arguments: [InterchainTokenService.objects.InterchainTokenService, TreasuryCap, Metadata], typeArguments: [tokenType], }); - await broadcastFromTxBuilder(postDeployTxBuilder, keypair, `Setup ${symbol} as a non-origin in ITS successfully`, options, { - showEvents: true, - }); + await broadcastFromTxBuilder( + postDeployTxBuilder, + keypair, + `Setup ${symbol} as a non-origin in InterchainTokenService successfully`, + options, + { + showEvents: true, + }, + ); } // Save the deployed token info in the contracts object. @@ -234,7 +237,7 @@ async function deployToken(keypair, client, contracts, args, options) { } async function printReceiveDeploymentInfo(contracts, args, options) { - const [name, symbol, decimals] = args; + const [sourceChain, name, symbol, decimals] = args; const messageType = ITSMessageType.InterchainTokenDeployment; const tokenId = options.tokenId; @@ -243,11 +246,12 @@ async function printReceiveDeploymentInfo(contracts, args, options) { const tokenDecimals = parseInt(decimals); const tokenDistributor = options.distributor; - // ITS transfer payload from Ethereum to Sui - const payload = defaultAbiCoder.encode( + // InterchainTokenService transfer payload from Ethereum to Sui + let payload = defaultAbiCoder.encode( ['uint256', 'uint256', 'bytes', 'bytes', 'uint256', 'bytes'], [messageType, tokenId, byteName, byteSymbol, tokenDecimals, tokenDistributor], ); + payload = defaultAbiCoder.encode(['uint256', 'string', 'bytes'], [ITSMessageType.ReceiveFromItsHub, sourceChain, payload]); printInfo( JSON.stringify( @@ -264,7 +268,7 @@ async function printReceiveDeploymentInfo(contracts, args, options) { async function printReceiveTransferInfo(contracts, args, options) { const { Example } = contracts; - const [symbol, sourceAddress, amount] = args; + const [sourceChain, symbol, sourceAddress, amount] = args; const Token = contracts[symbol]; const unitAmount = getUnitAmount(amount, Token.decimals); @@ -272,10 +276,11 @@ async function printReceiveTransferInfo(contracts, args, options) { const itsBytes = options.itsBytes; const channelId = options.channelId || Example.objects.ItsChannelId; - const payload = defaultAbiCoder.encode( + let payload = defaultAbiCoder.encode( ['uint256', 'uint256', 'bytes', 'bytes', 'uint256', 'bytes'], [ITSMessageType.InterchainTokenTransfer, tokenId, sourceAddress, channelId, unitAmount, itsBytes], ); + payload = defaultAbiCoder.encode(['uint256', 'string', 'bytes'], [ITSMessageType.ReceiveFromItsHub, sourceChain, payload]); printInfo( JSON.stringify( @@ -327,7 +332,7 @@ async function mainProcessor(command, options, args, processor) { if (require.main === module) { const program = new Command(); - program.name('ITS Example').description('SUI ITS Example scripts'); + program.name('InterchainTokenService Example').description('SUI InterchainTokenService Example scripts'); const sendTokenTransferProgram = new Command() .name('send-token') @@ -387,24 +392,24 @@ if (require.main === module) { const printDeploymentInfoProgram = new Command() .name('print-deployment-info') .description('Print deployment info. This script will be useful for testing receive deployment flow.') - .command('print-receive-deployment ') + .command('print-receive-deployment ') .addOption(new Option('--distributor ', 'Distributor address').default(ethers.constants.HashZero)) .addOption(new Option('--tokenId ', 'Token ID').default(hexlify(randomBytes(32)))) - .action((name, symbol, decimals, options) => { + .action((sourceChain, name, symbol, decimals, options) => { const config = loadConfig(options.env); const chain = getChainConfig(config, options.chainName); - printReceiveDeploymentInfo(chain.contracts, [name, symbol, decimals], options); + printReceiveDeploymentInfo(chain.contracts, [sourceChain, name, symbol, decimals], options); }); const printReceiveTransferInfoProgram = new Command() .name('print-transfer-info') .description('Print receive token info. This script will be useful for testing receive token flow.') - .command('print-receive-transfer ') - .addOption(new Option('--itsBytes ', 'ITS Bytes').default(ethers.constants.HashZero)) - .action((symbol, sourceAddress, amount, options) => { + .command('print-receive-transfer ') + .addOption(new Option('--itsBytes ', 'InterchainTokenService Bytes').default(ethers.constants.HashZero)) + .action((sourceChain, symbol, sourceAddress, amount, options) => { const config = loadConfig(options.env); const chain = getChainConfig(config, options.chainName); - printReceiveTransferInfo(chain.contracts, [symbol, sourceAddress, amount], options); + printReceiveTransferInfo(chain.contracts, [sourceChain, symbol, sourceAddress, amount], options); }); program.addCommand(sendTokenTransferProgram); diff --git a/sui/its.js b/sui/its.js index 21cc22921..87f9e4617 100644 --- a/sui/its.js +++ b/sui/its.js @@ -4,85 +4,62 @@ const { loadConfig, saveConfig, getChainConfig } = require('../common/utils'); const { addBaseOptions, addOptionsToCommands, getWallet, printWalletInfo, broadcastFromTxBuilder, saveGeneratedTx } = require('./utils'); const SPECIAL_CHAINS_TAGS = { - ALL_EVM: 'all-evm', // All EVM chains that have ITS deployed + ALL_EVM: 'all-evm', // All EVM chains that have InterchainTokenService deployed }; -function parseTrustedChains(config, trustedChain) { - if (trustedChain === SPECIAL_CHAINS_TAGS.ALL_EVM) { - const evmChains = Object.keys(config.chains).filter( - (chain) => config.chains[chain].chainType === 'evm' && config.chains[chain].contracts.InterchainTokenService, - ); +function parseTrustedChains(config, trustedChains) { + if (trustedChains === SPECIAL_CHAINS_TAGS.ALL_EVM) { + const evmChains = Object.keys(config.chains).filter((chain) => config.chains[chain].contracts?.InterchainTokenService?.address); return evmChains; } - return trustedChain.split(','); + return trustedChains; } -async function setupTrustedAddress(keypair, client, config, contracts, args, options) { - const [trustedChain, trustedAddress] = args; +async function addTrustedChains(keypair, client, config, contracts, args, options) { + const [trustedChain] = args; - const { ITS: itsConfig } = contracts; + const { InterchainTokenService: itsConfig } = contracts; - const { OwnerCap, ITS } = itsConfig.objects; + const { OwnerCap, InterchainTokenService } = itsConfig.objects; const txBuilder = new TxBuilder(client); const trustedChains = parseTrustedChains(config, trustedChain); - const trustedAddressesObject = await txBuilder.moveCall({ - target: `${itsConfig.address}::trusted_addresses::new`, - arguments: [trustedChains, trustedChains.map(() => trustedAddress)], - }); - await txBuilder.moveCall({ - target: `${itsConfig.address}::its::set_trusted_addresses`, - arguments: [ITS, OwnerCap, trustedAddressesObject], + target: `${itsConfig.address}::interchain_token_service::add_trusted_chains`, + arguments: [InterchainTokenService, OwnerCap, trustedChains], }); if (options.offline) { const tx = txBuilder.tx; const sender = options.sender || keypair.toSuiAddress(); tx.setSender(sender); - await saveGeneratedTx(tx, `Set trusted address for ${trustedChain} to ${trustedAddress}`, client, options); + await saveGeneratedTx(tx, `Added trusted chain ${trustedChain}`, client, options); } else { await broadcastFromTxBuilder(txBuilder, keypair, 'Setup Trusted Address', options); } - - // Update ITS config - for (const trustedChain of trustedChains) { - // Add trusted address to ITS config - if (!contracts.ITS.trustedAddresses) contracts.ITS.trustedAddresses = {}; - - contracts.ITS.trustedAddresses[trustedChain] = trustedAddress; - } } -async function removeTrustedAddress(keypair, client, contracts, args, options) { +async function removeTrustedChain(keypair, client, contracts, args, options) { const [trustedChain] = args; - const trustedAddressesObject = contracts.ITS.trustedAddresses; - - if (!trustedAddressesObject) throw new Error('No trusted addresses found'); - const chainNames = trustedChain.split(','); if (chainNames.length === 0) throw new Error('No chain names provided'); const txBuilder = new TxBuilder(client); - for (const chainName of chainNames) { - if (!trustedAddressesObject[chainName]) throw new Error(`No trusted addresses found for chain ${trustedChain}`); - } - await txBuilder.moveCall({ - target: `${contracts.ITS.address}::its::remove_trusted_addresses`, - arguments: [contracts.ITS.objects.ITS, contracts.ITS.objects.OwnerCap, chainNames], + target: `${contracts.InterchainTokenService.address}::interchain_token_service::remove_trusted_chains`, + arguments: [ + contracts.InterchainTokenService.objects.InterchainTokenService, + contracts.InterchainTokenService.objects.OwnerCap, + chainNames, + ], }); - for (const chainName of chainNames) { - delete contracts.ITS.trustedAddresses[chainName]; - } - await broadcastFromTxBuilder(txBuilder, keypair, 'Remove Trusted Address', options); } @@ -103,30 +80,30 @@ async function mainProcessor(command, options, args, processor) { if (require.main === module) { const program = new Command(); - program.name('ITS').description('SUI ITS scripts'); + program.name('InterchainTokenService').description('SUI InterchainTokenService scripts'); - // This command is used to setup the trusted address on the ITS contract. + // This command is used to setup the trusted address on the InterchainTokenService contract. // The trusted address is used to verify the message from the source chain. - const setupTrustedAddressProgram = new Command() - .name('setup-trusted-address') - .command('setup-trusted-address ') + const addTrustedChainsProgram = new Command() + .name('add-trusted-chains') + .command('add-trusted-chains ') .description( - `Setup trusted address. The can be a list of chains separated by commas. It can also be a special tag to indicate a specific set of chains e.g. '${SPECIAL_CHAINS_TAGS.ALL_EVM}' to target all ITS-deployed EVM chains`, + `Add trusted chains. The can be a list of chains separated by commas. It can also be a special tag to indicate a specific set of chains e.g. '${SPECIAL_CHAINS_TAGS.ALL_EVM}' to target all InterchainTokenService-deployed chains`, ) - .action((trustedChain, trustedAddress, options) => { - mainProcessor(setupTrustedAddress, options, [trustedChain, trustedAddress], processCommand); + .action((trustedChains, options) => { + mainProcessor(addTrustedChains, options, [trustedChains], processCommand); }); - const removeTrustedAddressProgram = new Command() + const removeTrustedChainsProgram = new Command() .name('remove-trusted-address') .description('Remove trusted address') - .command('remove-trusted-address ') - .action((trustedChain, options) => { - mainProcessor(removeTrustedAddress, options, [trustedChain], processCommand); + .command('remove-trusted-address ') + .action((trustedChains, options) => { + mainProcessor(removeTrustedChain, options, [trustedChains], processCommand); }); - program.addCommand(setupTrustedAddressProgram); - program.addCommand(removeTrustedAddressProgram); + program.addCommand(addTrustedChainsProgram); + program.addCommand(removeTrustedChainsProgram); addOptionsToCommands(program, addBaseOptions, { offline: true }); diff --git a/sui/utils/utils.js b/sui/utils/utils.js index 940134fec..cc11ce296 100644 --- a/sui/utils/utils.js +++ b/sui/utils/utils.js @@ -60,7 +60,6 @@ const getBcsBytesByObjectId = async (client, objectId) => { showBcs: true, }, }); - return fromB64(response.data.bcs.bcsBytes); }; @@ -128,7 +127,7 @@ const getSingletonChannelId = async (client, singletonObjectId) => { const getItsChannelId = async (client, itsObjectId) => { const bcsBytes = await getBcsBytesByObjectId(client, itsObjectId); - const data = bcsStructs.its.ITS.parse(bcsBytes); + const data = bcsStructs.its.InterchainTokenService.parse(bcsBytes); const channelId = data.value.channel.id; return '0x' + channelId; }; @@ -266,12 +265,8 @@ const parseGatewayInfo = (chain) => { }; }; -const checkTrustedAddresses = (trustedAddresses, destinationChain) => { - if (!trustedAddresses[destinationChain]) { - throw new Error( - `${destinationChain} is not trusted. Run 'node sui/its-example.js setup-trusted-address ' to setup trusted address`, - ); - } +const checkTrustedAddresses = async (destinationChain) => { + // TODO: another PR adds functionality that will enable this }; const getStructs = async (client, packageId) => {