diff --git a/contracts/InterchainTokenFactory.sol b/contracts/InterchainTokenFactory.sol index 83d83cb2..cb726f76 100644 --- a/contracts/InterchainTokenFactory.sol +++ b/contracts/InterchainTokenFactory.sol @@ -123,6 +123,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M * @param initialSupply The amount of tokens to mint initially (can be zero), allocated to the msg.sender. * @param minter The address to receive the minter and operator role of the token, in addition to ITS. If it is set to `address(0)`, * the additional minter isn't set, and can't be added later. This allows creating tokens that are managed only by ITS, reducing trust assumptions. + * Reverts if the minter is the ITS address since it's already added as a minter. * @return tokenId The tokenId corresponding to the deployed InterchainToken. */ function deployInterchainToken( @@ -140,6 +141,8 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M if (initialSupply > 0) { minterBytes = address(this).toBytes(); } else if (minter != address(0)) { + if (minter == address(interchainTokenService)) revert InvalidMinter(minter); + minterBytes = minter.toBytes(); } @@ -165,7 +168,8 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M * @notice Deploys a remote interchain token on a specified destination chain. * @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. + * @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 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. @@ -202,6 +206,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M if (minter != address(0)) { if (!token.isMinter(minter)) revert NotMinter(minter); + if (minter == address(interchainTokenService)) revert InvalidMinter(minter); minter_ = minter.toBytes(); } diff --git a/contracts/interfaces/IInterchainTokenFactory.sol b/contracts/interfaces/IInterchainTokenFactory.sol index ea07bbe2..ec1fabad 100644 --- a/contracts/interfaces/IInterchainTokenFactory.sol +++ b/contracts/interfaces/IInterchainTokenFactory.sol @@ -14,6 +14,7 @@ import { IInterchainTokenService } from './IInterchainTokenService.sol'; interface IInterchainTokenFactory is IUpgradable, IMulticall { error ZeroAddress(); error InvalidChainName(); + error InvalidMinter(address minter); error NotMinter(address minter); error NotOperator(address operator); error GatewayToken(address tokenAddress); diff --git a/test/InterchainTokenFactory.js b/test/InterchainTokenFactory.js index 2c3f6caa..573c7731 100644 --- a/test/InterchainTokenFactory.js +++ b/test/InterchainTokenFactory.js @@ -270,6 +270,16 @@ describe('InterchainTokenFactory', () => { expect(await tokenManager.isFlowLimiter(service.address)).to.be.true; }; + it('Should revert an interchain token deployment with the minter as interchainTokenService', async () => { + const salt = keccak256('0x1245'); + await expectRevert( + (gasOptions) => tokenFactory.deployInterchainToken(salt, name, symbol, decimals, 0, service.address, gasOptions), + tokenFactory, + 'InvalidMinter', + [service.address], + ); + }); + it('Should register a token if the mint amount is zero', async () => { const salt = keccak256('0x1234'); tokenId = await tokenFactory.interchainTokenId(wallet.address, salt); @@ -400,6 +410,17 @@ describe('InterchainTokenFactory', () => { [otherWallet.address], ); + await expectRevert( + (gasOptions) => + tokenFactory.deployRemoteInterchainToken(chainName, salt, service.address, destinationChain, gasValue, { + ...gasOptions, + value: gasValue, + }), + tokenFactory, + 'InvalidMinter', + [service.address], + ); + await expect( tokenFactory.deployRemoteInterchainToken('', salt, wallet.address, destinationChain, gasValue, { value: gasValue,