From 8731388d219e131345ed7d4ed87b334a79d273af Mon Sep 17 00:00:00 2001 From: ahramy Date: Tue, 5 Nov 2024 17:57:49 -0800 Subject: [PATCH 1/5] feat(its-factory): allow minter to be arbitrary bytes for remote token deployment --- contracts/InterchainTokenFactory.sol | 27 ++++++++++++------- .../interfaces/IInterchainTokenFactory.sol | 6 +++-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/contracts/InterchainTokenFactory.sol b/contracts/InterchainTokenFactory.sol index ef936708..9cb65cdf 100644 --- a/contracts/InterchainTokenFactory.sol +++ b/contracts/InterchainTokenFactory.sol @@ -155,22 +155,23 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M /** * @notice Deploys a remote interchain token on a specified destination chain. * @param salt The unique salt for deploying the token. - * @param minter The address to receive the minter and operator role of the token, in addition to ITS. If the address is `address(0)`, - * no additional minter is set on the token. Reverts if the minter does not have mint permission for the token. + * @param localMinter TBD + * @param remoteMinter TBD * @param destinationChain The name of the destination chain. * @param gasValue The amount of gas to send for the deployment. * @return tokenId The tokenId corresponding to the deployed InterchainToken. */ function deployRemoteInterchainToken( bytes32 salt, - address minter, + address localMinter, + address remoteMinter, string memory destinationChain, uint256 gasValue ) public payable returns (bytes32 tokenId) { string memory tokenName; string memory tokenSymbol; uint8 tokenDecimals; - bytes memory minter_ = new bytes(0); + bytes memory remoteMinterBytes = new bytes(0); salt = interchainTokenSalt(chainNameHash, msg.sender, salt); tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt); @@ -181,14 +182,19 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M tokenSymbol = token.symbol(); tokenDecimals = token.decimals(); - if (minter != address(0)) { - if (!token.isMinter(minter)) revert NotMinter(minter); - if (minter == address(interchainTokenService)) revert InvalidMinter(minter); + if (localMinter != address(0)) { + if (!token.isMinter(localMinter)) revert NotMinter(localMinter); + if (localMinter == address(interchainTokenService)) revert InvalidMinter(localMinter); + } - minter_ = minter.toBytes(); + // Prepare remote minter for deployment on the destination chain + if (remoteMinter != address(0)) { + if (!token.isMinter(remoteMinter)) revert NotMinter(remoteMinter); + if (remoteMinter == address(interchainTokenService)) revert InvalidMinter(remoteMinter); + remoteMinterBytes = remoteMinter.toBytes(); } - tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, minter_, gasValue); + tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, remoteMinterBytes, gasValue); } /** @@ -204,6 +210,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M * @param gasValue The amount of gas to send for the deployment. * @return tokenId The tokenId corresponding to the deployed InterchainToken. */ + // This method is deprecated, should I remove it with the minter change or we want to keep it? function deployRemoteInterchainToken( string calldata originalChainName, bytes32 salt, @@ -213,7 +220,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M ) external payable returns (bytes32 tokenId) { if (bytes(originalChainName).length != 0) revert NotSupported(); - tokenId = deployRemoteInterchainToken(salt, minter, destinationChain, gasValue); + tokenId = deployRemoteInterchainToken(salt, minter, address(0), destinationChain, gasValue); } /** diff --git a/contracts/interfaces/IInterchainTokenFactory.sol b/contracts/interfaces/IInterchainTokenFactory.sol index 0dbdb311..198fa352 100644 --- a/contracts/interfaces/IInterchainTokenFactory.sol +++ b/contracts/interfaces/IInterchainTokenFactory.sol @@ -79,14 +79,16 @@ interface IInterchainTokenFactory is IUpgradable, IMulticall { /** * @notice Deploys a remote interchain token on a specified destination chain. * @param salt The unique salt for deploying the token. - * @param minter The address to distribute the token on the destination chain. + * @param localMinter TBD + * @param remoteMinter TBD * @param destinationChain The name of the destination chain. * @param gasValue The amount of gas to send for the deployment. * @return tokenId The tokenId corresponding to the deployed InterchainToken. */ function deployRemoteInterchainToken( bytes32 salt, - address minter, + address localMinter, + address remoteMinter, string memory destinationChain, uint256 gasValue ) external payable returns (bytes32 tokenId); From c90f14fb69b7851e3f29cdf50cd0220cf86942fb Mon Sep 17 00:00:00 2001 From: ahramy Date: Thu, 7 Nov 2024 11:10:34 -0800 Subject: [PATCH 2/5] updated --- contracts/InterchainTokenFactory.sol | 43 ++++++++++--------- .../interfaces/IInterchainTokenFactory.sol | 11 ++--- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/contracts/InterchainTokenFactory.sol b/contracts/InterchainTokenFactory.sol index 9cb65cdf..8611be83 100644 --- a/contracts/InterchainTokenFactory.sol +++ b/contracts/InterchainTokenFactory.sol @@ -155,23 +155,21 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M /** * @notice Deploys a remote interchain token on a specified destination chain. * @param salt The unique salt for deploying the token. - * @param localMinter TBD - * @param remoteMinter TBD + * @param remoteMinter The calldata representing the minter's address on the remote chain. Must be empty if no minter is specified. + * Reverts if the msg.sender does not have mint permission for the token. * @param destinationChain The name of the destination chain. * @param gasValue The amount of gas to send for the deployment. * @return tokenId The tokenId corresponding to the deployed InterchainToken. */ function deployRemoteInterchainToken( bytes32 salt, - address localMinter, - address remoteMinter, + bytes memory remoteMinter, string memory destinationChain, uint256 gasValue ) public payable returns (bytes32 tokenId) { string memory tokenName; string memory tokenSymbol; uint8 tokenDecimals; - bytes memory remoteMinterBytes = new bytes(0); salt = interchainTokenSalt(chainNameHash, msg.sender, salt); tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt); @@ -182,19 +180,12 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M tokenSymbol = token.symbol(); tokenDecimals = token.decimals(); - if (localMinter != address(0)) { - if (!token.isMinter(localMinter)) revert NotMinter(localMinter); - if (localMinter == address(interchainTokenService)) revert InvalidMinter(localMinter); + if (remoteMinter.length != 0) { + if (!token.isMinter(msg.sender)) revert NotMinter(msg.sender); + if (msg.sender == address(interchainTokenService)) revert InvalidMinter(msg.sender); } - // Prepare remote minter for deployment on the destination chain - if (remoteMinter != address(0)) { - if (!token.isMinter(remoteMinter)) revert NotMinter(remoteMinter); - if (remoteMinter == address(interchainTokenService)) revert InvalidMinter(remoteMinter); - remoteMinterBytes = remoteMinter.toBytes(); - } - - tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, remoteMinterBytes, gasValue); + tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, remoteMinter, gasValue); } /** @@ -204,23 +195,22 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M * Other source chains are not supported anymore to simplify ITS token deployment behaviour. * @param originalChainName The name of the chain where the token originally exists. * @param salt The unique salt for deploying the token. - * @param minter The address to receive the minter and operator role of the token, in addition to ITS. If the address is `address(0)`, + * @dev minter The address to receive the minter and operator role of the token, in addition to ITS. If the address is `address(0)`, * no additional minter is set on the token. Reverts if the minter does not have mint permission for the token. * @param destinationChain The name of the destination chain. * @param gasValue The amount of gas to send for the deployment. * @return tokenId The tokenId corresponding to the deployed InterchainToken. */ - // This method is deprecated, should I remove it with the minter change or we want to keep it? function deployRemoteInterchainToken( string calldata originalChainName, bytes32 salt, - address minter, + address /*minter*/, string memory destinationChain, uint256 gasValue ) external payable returns (bytes32 tokenId) { if (bytes(originalChainName).length != 0) revert NotSupported(); - tokenId = deployRemoteInterchainToken(salt, minter, address(0), destinationChain, gasValue); + tokenId = deployRemoteInterchainToken(salt, abi.encodePacked(address(0)), destinationChain, gasValue); } /** @@ -317,4 +307,17 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M tokenId = deployRemoteCanonicalInterchainToken(originalTokenAddress, destinationChain, gasValue); } + + function addressToBytes(address _address) public pure returns (bytes memory) { + return abi.encodePacked(_address); + } + + function bytesToAddress(bytes memory data) public pure returns (address) { + require(data.length == 20, 'Invalid bytes length for address'); + address addr; + assembly { + addr := mload(add(data, 20)) + } + return addr; + } } diff --git a/contracts/interfaces/IInterchainTokenFactory.sol b/contracts/interfaces/IInterchainTokenFactory.sol index 198fa352..3bfef386 100644 --- a/contracts/interfaces/IInterchainTokenFactory.sol +++ b/contracts/interfaces/IInterchainTokenFactory.sol @@ -79,27 +79,28 @@ interface IInterchainTokenFactory is IUpgradable, IMulticall { /** * @notice Deploys a remote interchain token on a specified destination chain. * @param salt The unique salt for deploying the token. - * @param localMinter TBD - * @param remoteMinter TBD + * @param remoteMinter The calldata representing the minter's address on the remote chain. Must be empty if no minter is specified. + * Reverts if the msg.sender does not have mint permission for the token. * @param destinationChain The name of the destination chain. * @param gasValue The amount of gas to send for the deployment. * @return tokenId The tokenId corresponding to the deployed InterchainToken. */ function deployRemoteInterchainToken( bytes32 salt, - address localMinter, - address remoteMinter, + bytes calldata remoteMinter, string memory destinationChain, uint256 gasValue ) external payable returns (bytes32 tokenId); /** * @notice Deploys a remote interchain token on a specified destination chain. + * This method is deprecated and will be removed in the future. Please use the above method instead. * @dev originalChainName is only allowed to be '', i.e the current chain. * Other source chains are not supported anymore to simplify ITS token deployment behaviour. * @param originalChainName The name of the chain where the token originally exists. * @param salt The unique salt for deploying the token. - * @param minter The address to distribute the token on the destination chain. + * @dev minter The address to receive the minter and operator role of the token, in addition to ITS. If the address is `address(0)`, + * no additional minter is set on the token. Reverts if the minter does not have mint permission for the token. * @param destinationChain The name of the destination chain. * @param gasValue The amount of gas to send for the deployment. * @return tokenId The tokenId corresponding to the deployed InterchainToken. From ddb8e3052d372e06e79a20b6d1d7d07cfa346d4a Mon Sep 17 00:00:00 2001 From: ahramy Date: Thu, 7 Nov 2024 11:12:10 -0800 Subject: [PATCH 3/5] Update InterchainTokenFactory.sol --- contracts/InterchainTokenFactory.sol | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/contracts/InterchainTokenFactory.sol b/contracts/InterchainTokenFactory.sol index 8611be83..93bc8d38 100644 --- a/contracts/InterchainTokenFactory.sol +++ b/contracts/InterchainTokenFactory.sol @@ -307,17 +307,4 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M tokenId = deployRemoteCanonicalInterchainToken(originalTokenAddress, destinationChain, gasValue); } - - function addressToBytes(address _address) public pure returns (bytes memory) { - return abi.encodePacked(_address); - } - - function bytesToAddress(bytes memory data) public pure returns (address) { - require(data.length == 20, 'Invalid bytes length for address'); - address addr; - assembly { - addr := mload(add(data, 20)) - } - return addr; - } } From 9ce9e970fb201f264d557a204bfeaf656a2f3881 Mon Sep 17 00:00:00 2001 From: ahramy Date: Thu, 7 Nov 2024 11:13:08 -0800 Subject: [PATCH 4/5] Update InterchainTokenFactory.sol --- contracts/InterchainTokenFactory.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/InterchainTokenFactory.sol b/contracts/InterchainTokenFactory.sol index 93bc8d38..67791a24 100644 --- a/contracts/InterchainTokenFactory.sol +++ b/contracts/InterchainTokenFactory.sol @@ -209,8 +209,9 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M uint256 gasValue ) external payable returns (bytes32 tokenId) { if (bytes(originalChainName).length != 0) revert NotSupported(); + bytes memory emptyMinter = new bytes(0); - tokenId = deployRemoteInterchainToken(salt, abi.encodePacked(address(0)), destinationChain, gasValue); + tokenId = deployRemoteInterchainToken(salt, emptyMinter, destinationChain, gasValue); } /** From 9783ac0ab8a1e49203591f4667569dedbfead4d9 Mon Sep 17 00:00:00 2001 From: ahramy Date: Thu, 7 Nov 2024 11:13:20 -0800 Subject: [PATCH 5/5] Update InterchainTokenFactory.sol --- contracts/InterchainTokenFactory.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/InterchainTokenFactory.sol b/contracts/InterchainTokenFactory.sol index 67791a24..ebbad527 100644 --- a/contracts/InterchainTokenFactory.sol +++ b/contracts/InterchainTokenFactory.sol @@ -209,9 +209,9 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M uint256 gasValue ) external payable returns (bytes32 tokenId) { if (bytes(originalChainName).length != 0) revert NotSupported(); - bytes memory emptyMinter = new bytes(0); + bytes memory minter_ = new bytes(0); - tokenId = deployRemoteInterchainToken(salt, emptyMinter, destinationChain, gasValue); + tokenId = deployRemoteInterchainToken(salt, minter_, destinationChain, gasValue); } /**