From 8b8b4b54d8d383c1b9f082fecf8c739c4e1d0b0b Mon Sep 17 00:00:00 2001 From: Milap Sheth Date: Tue, 25 Feb 2025 11:48:34 -0400 Subject: [PATCH] feat(evm): add legacy ITS custom token linkToken support --- evm/README.md | 14 ++++++++++++++ evm/its.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/evm/README.md b/evm/README.md index ce1ef926f..969bf7fe8 100644 --- a/evm/README.md +++ b/evm/README.md @@ -257,3 +257,17 @@ To get details of options provided in the command run: ```bash node evm/verify-contract.js --help ``` + +## Interchain Token Service + +### Link Token + +#### Legacy custom ITS tokens + +Custom tokens that have already registered with ITS (via `deployTokenManager`) prior to ITS v2.1.0 release can continue being linked to new chains via the following approach. However, we do recommend registering them. Token manager type should be passed in via `--type` flag (e.g. `MINT_BURN`). + +```bash +node evm/its.js linkToken --salt [deploy-salt] --destinationChain [destinationChain] --tokenAddress [tokenAddress] --type [type] --operator [operator] --gasValue [gasValue] +``` + +The raw `bytes32` salt can be provided via `--rawSalt [raw-salt]` instead of hashing the provided salt string. diff --git a/evm/its.js b/evm/its.js index 0350eed7a..b0cd59cbd 100644 --- a/evm/its.js +++ b/evm/its.js @@ -634,6 +634,50 @@ async function processCommand(config, chain, options) { break; } + case 'linkToken': { + const { destinationChain, type, operator, tokenAddress, gasValue } = options; + + const deploymentSalt = getDeploymentSalt(options); + const tokenManagerType = tokenManagerImplementations[type]; + + validateParameters({ + isString: { destinationChain }, + isValidAddress: { tokenAddress, operator }, + isValidNumber: { gasValue, tokenManagerType }, + }); + isValidDestinationChain(config, destinationChain); + + const interchainTokenId = await interchainTokenService.interchainTokenId(wallet.address, deploymentSalt); + printInfo('Expected tokenId', interchainTokenId); + + try { + const tokenManagerAddress = await interchainTokenService.deployedTokenManager(tokenId); + printInfo(`TokenManager for tokenId ${tokenId} exists on the current chain`, tokenManagerAddress); + + const sourceTokenAddress = await interchainTokenService.registeredTokenAddress(tokenId); + printInfo(`Token address on current chain for tokenId ${tokenId}`, sourceTokenAddress); + } catch (error) { + printError(`TokenManager for tokenId ${tokenId} does not yet exist on the current chain.`); + return; + } + + const linkParams = operator; + + const tx = await interchainTokenService.linkToken( + deploymentSalt, + destinationChain, + tokenAddress, + tokenManagerType, + linkParams, + gasValue, + gasOptions, + ); + + await handleTx(tx, chain, interchainTokenService, options.action, 'LinkTokenStarted'); + + break; + } + default: { throw new Error(`Unknown action ${action}`); } @@ -677,6 +721,7 @@ if (require.main === module) { 'migrateInterchainToken', 'registerTokenMetadata', 'transferMintership', + 'linkToken', ]) .makeOptionMandatory(true), );