Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: preventing original chain name & destination chain name are the same #277

Merged
merged 12 commits into from
Sep 27, 2024
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.
ahramy marked this conversation as resolved.
Show resolved Hide resolved
* 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.
ahramy marked this conversation as resolved.
Show resolved Hide resolved
* 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(
ahramy marked this conversation as resolved.
Show resolved Hide resolved
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
Loading