Skip to content

Commit

Permalink
Merge branch 'main' into feat/remote-minter
Browse files Browse the repository at this point in the history
  • Loading branch information
milapsheth authored Nov 11, 2024
2 parents 9a6f87f + 38698a2 commit cbd6065
Show file tree
Hide file tree
Showing 9 changed files with 248 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/hungry-seahorses-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@axelar-network/interchain-token-service': patch
---

Remove support for deploying token manager to chains connected via ITS Hub. When deploying ITS to an EVM chain connected via Amplifier / ITS Hub, a trusted address must be set for it's own chain name to the `'hub'` identifier, to prevent deploying the token manager locally. Note that this restriction is temporary. Once the ITS Hub adds support for deploy token manager msg type, the restriction will be removed. Also note that the token manager deployed as part of registering a canonical ITS token from the ITS Factory is not affected by this.
2 changes: 2 additions & 0 deletions contracts/InterchainTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M
/**
* @notice Deploys a new interchain token with specified parameters.
* @dev Creates a new token and optionally mints an initial amount to a specified minter.
* This function is `payable` because non-payable functions cannot be called in a multicall that calls other `payable` functions.
* @param salt The unique salt for deploying the token.
* @param name The name of the token.
* @param symbol The symbol of the token.
Expand Down Expand Up @@ -350,6 +351,7 @@ contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, M

/**
* @notice Registers a canonical token as an interchain token and deploys its token manager.
* @dev This function is `payable` because non-payable functions cannot be called in a multicall that calls other `payable` functions.
* @param tokenAddress The address of the canonical token.
* @return tokenId The tokenId corresponding to the registered canonical token.
*/
Expand Down
25 changes: 25 additions & 0 deletions contracts/InterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,11 @@ contract InterchainTokenService is
* @notice Used to deploy remote custom TokenManagers.
* @dev At least the `gasValue` amount of native token must be passed to the function call. `gasValue` exists because this function can be
* part of a multicall involving multiple functions that could make remote contract calls.
* This method is temporarily restricted in the following scenarios:
* - Deploying to a remote chain and the destination chain is connected via ITS Hub
* - Deploying to the current chain, if connected as an Amplifier chain, i.e existing ITS contracts on consensus chains aren't affected.
* Once ITS Hub adds support for deploy token manager msg, the restriction will be lifted.
* Note that the factory contract can still call `deployTokenManager` to facilitate canonical token registration.
* @param salt The salt to be used during deployment.
* @param destinationChain The name of the chain to deploy the TokenManager and standardized token to.
* @param tokenManagerType The type of token manager to be deployed. Cannot be NATIVE_INTERCHAIN_TOKEN.
Expand All @@ -297,13 +302,18 @@ contract InterchainTokenService is
bytes calldata params,
uint256 gasValue
) external payable whenNotPaused returns (bytes32 tokenId) {
if (bytes(params).length == 0) revert EmptyParams();

// Custom token managers can't be deployed with native interchain token type, which is reserved for interchain tokens
if (tokenManagerType == TokenManagerType.NATIVE_INTERCHAIN_TOKEN) revert CannotDeploy(tokenManagerType);

address deployer = msg.sender;

if (deployer == interchainTokenFactory) {
deployer = TOKEN_FACTORY_DEPLOYER;
} else if (bytes(destinationChain).length == 0 && trustedAddressHash(chainName()) == ITS_HUB_ROUTING_IDENTIFIER_HASH) {
// Restricted on ITS contracts deployed to Amplifier chains until ITS Hub adds support
revert NotSupported();
}

tokenId = interchainTokenId(deployer, salt);
Expand Down Expand Up @@ -382,6 +392,7 @@ contract InterchainTokenService is

/**
* @notice Express executes operations based on the payload and selector.
* @dev This function is `payable` because non-payable functions cannot be called in a multicall that calls other `payable` functions.
* @param commandId The unique message id.
* @param sourceChain The chain where the transaction originates from.
* @param sourceAddress The address of the remote ITS where the transaction originates from.
Expand Down Expand Up @@ -515,6 +526,7 @@ contract InterchainTokenService is
uint256 gasValue
) external payable whenNotPaused {
if (data.length == 0) revert EmptyData();

amount = _takeToken(tokenId, msg.sender, amount, false);

_transmitInterchainTransfer(
Expand Down Expand Up @@ -787,6 +799,9 @@ contract InterchainTokenService is

// Check whether the ITS call should be routed via ITS hub for this destination chain
if (keccak256(abi.encodePacked(destinationAddress)) == ITS_HUB_ROUTING_IDENTIFIER_HASH) {
// Prevent deploy token manager to be usable on ITS hub
if (_getMessageType(payload) == MESSAGE_TYPE_DEPLOY_TOKEN_MANAGER) revert NotSupported();

// Wrap ITS message in an ITS Hub message
payload = abi.encode(MESSAGE_TYPE_SEND_TO_HUB, destinationChain, payload);
destinationChain = ITS_HUB_CHAIN_NAME;
Expand Down Expand Up @@ -855,6 +870,9 @@ contract InterchainTokenService is

// Get message type of the inner ITS message
messageType = _getMessageType(payload);

// Prevent deploy token manager to be usable on ITS hub
if (messageType == MESSAGE_TYPE_DEPLOY_TOKEN_MANAGER) revert NotSupported();
} else {
// Prevent receiving a direct message from the ITS Hub. This is not supported yet.
if (keccak256(abi.encodePacked(sourceChain)) == ITS_HUB_CHAIN_NAME_HASH) revert UntrustedChain();
Expand Down Expand Up @@ -907,6 +925,9 @@ contract InterchainTokenService is
string calldata destinationChain,
uint256 gasValue
) internal {
if (bytes(name).length == 0) revert EmptyTokenName();
if (bytes(symbol).length == 0) revert EmptyTokenSymbol();

// slither-disable-next-line unused-return
deployedTokenManager(tokenId);

Expand Down Expand Up @@ -968,6 +989,9 @@ contract InterchainTokenService is
string memory symbol,
uint8 decimals
) internal returns (address tokenAddress) {
if (bytes(name).length == 0) revert EmptyTokenName();
if (bytes(symbol).length == 0) revert EmptyTokenSymbol();

bytes32 salt = _getInterchainTokenSalt(tokenId);

address minter;
Expand Down Expand Up @@ -1029,6 +1053,7 @@ contract InterchainTokenService is
bytes memory data,
uint256 gasValue
) internal {
if (destinationAddress.length == 0) revert EmptyDestinationAddress();
if (amount == 0) revert ZeroAmount();

// slither-disable-next-line reentrancy-events
Expand Down
6 changes: 2 additions & 4 deletions contracts/TokenHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ contract TokenHandler is ITokenHandler, ITokenManagerType, ReentrancyGuard, Crea
* @return uint256 The amount of token actually given, which could be different for certain token type.
* @return address the address of the token.
*/
// slither-disable-next-line locked-ether
function giveToken(bytes32 tokenId, address to, uint256 amount) external payable returns (uint256, address) {
function giveToken(bytes32 tokenId, address to, uint256 amount) external returns (uint256, address) {
address tokenManager = _create3Address(tokenId);

(uint256 tokenManagerType, address tokenAddress) = ITokenManagerProxy(tokenManager).getImplementationTypeAndTokenAddress();
Expand Down Expand Up @@ -107,8 +106,7 @@ contract TokenHandler is ITokenHandler, ITokenManagerType, ReentrancyGuard, Crea
* @return uint256 The amount of token actually transferred, which could be different for certain token type.
* @return address The address of the token corresponding to the input tokenId.
*/
// slither-disable-next-line locked-ether
function transferTokenFrom(bytes32 tokenId, address from, address to, uint256 amount) external payable returns (uint256, address) {
function transferTokenFrom(bytes32 tokenId, address from, address to, uint256 amount) external returns (uint256, address) {
address tokenManager = _create3Address(tokenId);
(uint256 tokenManagerType, address tokenAddress) = ITokenManagerProxy(tokenManager).getImplementationTypeAndTokenAddress();

Expand Down
5 changes: 5 additions & 0 deletions contracts/interfaces/IInterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ interface IInterchainTokenService is
error CannotDeployRemotelyToSelf();
error InvalidPayload();
error GatewayCallFailed(bytes data);
error EmptyTokenName();
error EmptyTokenSymbol();
error EmptyParams();
error EmptyDestinationAddress();
error NotSupported();

event InterchainTransfer(
bytes32 indexed tokenId,
Expand Down
5 changes: 2 additions & 3 deletions contracts/interfaces/ITokenHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface ITokenHandler {
* @return uint256 The amount of token actually given, which could be different for certain token type.
* @return address the address of the token.
*/
function giveToken(bytes32 tokenId, address to, uint256 amount) external payable returns (uint256, address);
function giveToken(bytes32 tokenId, address to, uint256 amount) external returns (uint256, address);

/**
* @notice This function takes token from a specified address to the token manager.
Expand All @@ -40,8 +40,7 @@ interface ITokenHandler {
* @return uint256 The amount of token actually transferred, which could be different for certain token type.
* @return address The address of the token corresponding to the input tokenId.
*/
// slither-disable-next-line locked-ether
function transferTokenFrom(bytes32 tokenId, address from, address to, uint256 amount) external payable returns (uint256, address);
function transferTokenFrom(bytes32 tokenId, address from, address to, uint256 amount) external returns (uint256, address);

/**
* @notice This function prepares a token manager after it is deployed
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
},
"dependencies": {
"@axelar-network/axelar-cgp-solidity": "6.4.0",
"@axelar-network/axelar-gmp-sdk-solidity": "6.0.3"
"@axelar-network/axelar-gmp-sdk-solidity": "6.0.4"
},
"devDependencies": {
"@axelar-network/axelar-chains-config": "^1.3.0",
Expand Down
Loading

0 comments on commit cbd6065

Please sign in to comment.