Skip to content

Commit

Permalink
fix: preventing original chain name & destination chain name are the …
Browse files Browse the repository at this point in the history
…same (#277)

Co-authored-by: Milap Sheth <milap@interoplabs.io>
  • Loading branch information
ahramy and milapsheth authored Sep 27, 2024
1 parent b680103 commit 92cbbf1
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 64 deletions.
101 changes: 63 additions & 38 deletions contracts/InterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ 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 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.
Expand All @@ -175,46 +174,60 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
* @return tokenId The tokenId corresponding to the deployed InterchainToken.
*/
function deployRemoteInterchainToken(
string calldata originalChainName,
bytes32 salt,
address minter,
string memory destinationChain,
uint256 gasValue
) external payable returns (bytes32 tokenId) {
) public payable returns (bytes32 tokenId) {
string memory tokenName;
string memory tokenSymbol;
uint8 tokenDecimals;
bytes memory minter_ = new bytes(0);

{
bytes32 chainNameHash_;
if (bytes(originalChainName).length == 0) {
chainNameHash_ = chainNameHash;
} else {
chainNameHash_ = keccak256(bytes(originalChainName));
}
salt = interchainTokenSalt(chainNameHash, msg.sender, salt);
tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);

address sender = msg.sender;
salt = interchainTokenSalt(chainNameHash_, sender, salt);
tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);
IInterchainToken token = IInterchainToken(interchainTokenService.interchainTokenAddress(tokenId));

IInterchainToken token = IInterchainToken(interchainTokenService.interchainTokenAddress(tokenId));

tokenName = token.name();
tokenSymbol = token.symbol();
tokenDecimals = token.decimals();
tokenName = token.name();
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 (minter != address(0)) {
if (!token.isMinter(minter)) revert NotMinter(minter);
if (minter == address(interchainTokenService)) revert InvalidMinter(minter);

minter_ = minter.toBytes();
}
minter_ = minter.toBytes();
}

tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, minter_, gasValue);
}

/**
* @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 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.
*/
function deployRemoteInterchainToken(
string calldata originalChainName,
bytes32 salt,
address minter,
string memory destinationChain,
uint256 gasValue
) external payable returns (bytes32 tokenId) {
if (bytes(originalChainName).length != 0) revert NotSupported();

tokenId = deployRemoteInterchainToken(salt, minter, destinationChain, gasValue);
}

/**
* @notice Deploys a new interchain token with specified parameters.
* @param salt The unique salt for deploying the token.
Expand Down Expand Up @@ -263,33 +276,23 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M

/**
* @notice Deploys a canonical interchain token on a remote chain.
* @param originalChain The name of the chain where the token originally exists.
* @param originalTokenAddress The address of the original token on the original chain.
* @param destinationChain The name of the chain where the token will be deployed.
* @param gasValue The gas amount to be sent for deployment.
* @return tokenId The tokenId corresponding to the deployed InterchainToken.
*/
function deployRemoteCanonicalInterchainToken(
string calldata originalChain,
address originalTokenAddress,
string calldata destinationChain,
uint256 gasValue
) external payable returns (bytes32 tokenId) {
) public payable returns (bytes32 tokenId) {
bytes32 salt;
IInterchainToken token;

{
bytes32 chainNameHash_;
if (bytes(originalChain).length == 0) {
chainNameHash_ = chainNameHash;
} else {
chainNameHash_ = keccak256(bytes(originalChain));
}
// This ensures that the token manager has been deployed by this address, so it's safe to trust it.
salt = canonicalInterchainTokenSalt(chainNameHash_, originalTokenAddress);
tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);
token = IInterchainToken(interchainTokenService.validTokenAddress(tokenId));
}
// This ensures that the token manager has been deployed by this address, so it's safe to trust it.
salt = canonicalInterchainTokenSalt(chainNameHash, originalTokenAddress);
tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);
token = IInterchainToken(interchainTokenService.validTokenAddress(tokenId));

// The 3 lines below will revert if the token does not exist.
string memory tokenName = token.name();
Expand All @@ -299,6 +302,28 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, '', gasValue);
}

/**
* @notice Deploys a canonical interchain token on a remote chain.
* This method is deprecated and will be removed in the future. Please use the above method instead.
* @dev originalChain is only allowed to be '', i.e the current chain.
* Other source chains are not supported anymore to simplify ITS token deployment behaviour.
* @param originalChain The name of the chain where the token originally exists.
* @param originalTokenAddress The address of the original token on the original chain.
* @param destinationChain The name of the chain where the token will be deployed.
* @param gasValue The gas amount to be sent for deployment.
* @return tokenId The tokenId corresponding to the deployed InterchainToken.
*/
function deployRemoteCanonicalInterchainToken(
string calldata originalChain,
address originalTokenAddress,
string calldata destinationChain,
uint256 gasValue
) external payable returns (bytes32 tokenId) {
if (bytes(originalChain).length != 0) revert NotSupported();

tokenId = deployRemoteCanonicalInterchainToken(originalTokenAddress, destinationChain, gasValue);
}

/**
* @notice Register 'canonical' gateway tokens. The same salt needs to be used for the same gateway token on every chain.
* @param tokenIdentifier A gateway token identifier to be used for the token registration. Should be the same for all chains.
Expand Down
4 changes: 4 additions & 0 deletions contracts/InterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ contract InterchainTokenService is
if (bytes(destinationChain).length == 0) {
_deployTokenManager(tokenId, tokenManagerType, params);
} else {
if (chainNameHash == keccak256(bytes(destinationChain))) revert CannotDeployRemotelyToSelf();

_deployRemoteTokenManager(tokenId, destinationChain, gasValue, tokenManagerType, params);
}
}
Expand Down Expand Up @@ -348,6 +350,8 @@ contract InterchainTokenService is

_deployTokenManager(tokenId, TokenManagerType.NATIVE_INTERCHAIN_TOKEN, abi.encode(minter, tokenAddress));
} else {
if (chainNameHash == keccak256(bytes(destinationChain))) revert CannotDeployRemotelyToSelf();

_deployRemoteInterchainToken(tokenId, name, symbol, decimals, minter, destinationChain, gasValue);
}
}
Expand Down
33 changes: 33 additions & 0 deletions contracts/interfaces/IInterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface IInterchainTokenFactory is IUpgradable, IMulticall {
error GatewayToken(address tokenAddress);
error NotServiceOwner(address sender);
error NotGatewayToken(string symbol);
error NotSupported();

/**
* @notice Returns the address of the interchain token service.
Expand Down Expand Up @@ -79,6 +80,23 @@ 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 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,
string memory destinationChain,
uint256 gasValue
) external payable returns (bytes32 tokenId);

/**
* @notice Deploys a remote interchain token on a specified destination chain.
* @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.
Expand Down Expand Up @@ -118,6 +136,21 @@ interface IInterchainTokenFactory is IUpgradable, IMulticall {

/**
* @notice Deploys a canonical interchain token on a remote chain.
* @param originalTokenAddress The address of the original token on the original chain.
* @param destinationChain The name of the chain where the token will be deployed.
* @param gasValue The gas amount to be sent for deployment.
* @return tokenId The tokenId corresponding to the deployed canonical InterchainToken.
*/
function deployRemoteCanonicalInterchainToken(
address originalTokenAddress,
string calldata destinationChain,
uint256 gasValue
) external payable returns (bytes32 tokenId);

/**
* @notice Deploys a canonical interchain token on a remote chain.
* @dev originalChain is only allowed to be '', i.e the current chain.
* Other source chains are not supported anymore to simplify ITS token deployment behaviour.
* @param originalChain The name of the chain where the token originally exists.
* @param originalTokenAddress The address of the original token on the original chain.
* @param destinationChain The name of the chain where the token will be deployed.
Expand Down
1 change: 1 addition & 0 deletions contracts/interfaces/IInterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ interface IInterchainTokenService is
error PostDeployFailed(bytes data);
error ZeroAmount();
error CannotDeploy(TokenManagerType);
error CannotDeployRemotelyToSelf();
error InvalidGatewayTokenTransfer(bytes32 tokenId, bytes payload, string tokenSymbol, uint256 amount);
error InvalidPayload();
error GatewayCallFailed(bytes data);
Expand Down
2 changes: 1 addition & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const itsCompilerSettings = {
evmVersion: process.env.EVM_VERSION || 'london',
optimizer: {
...optimizerSettings,
runs: 150, // Reduce runs to keep bytecode size under limit
runs: 100, // Reduce runs to keep bytecode size under limit
},
},
};
Expand Down
Loading

0 comments on commit 92cbbf1

Please sign in to comment.