Skip to content

Commit

Permalink
feat(its): prevent deploy token manager on its hub (#299)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahramy authored Nov 11, 2024
1 parent 3d0a371 commit 38698a2
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 5 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.
14 changes: 14 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 @@ -306,6 +311,9 @@ contract InterchainTokenService is

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 @@ -791,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 @@ -859,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
1 change: 1 addition & 0 deletions contracts/interfaces/IInterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ interface IInterchainTokenService is
error EmptyTokenSymbol();
error EmptyParams();
error EmptyDestinationAddress();
error NotSupported();

event InterchainTransfer(
bytes32 indexed tokenId,
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
82 changes: 82 additions & 0 deletions test/InterchainTokenService.js
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,22 @@ describe('Interchain Token Service', () => {

await service.setPauseStatus(false).then((tx) => tx.wait);
});

it('Should revert with NotSupported when deploying a token manager on its hub chain', async () => {
const params = defaultAbiCoder.encode(['bytes', 'address'], [wallet.address, token.address]);

await expect(service.setTrustedAddress(chainName, ITS_HUB_ROUTING_IDENTIFIER))
.to.emit(service, 'TrustedAddressSet')
.withArgs(chainName, ITS_HUB_ROUTING_IDENTIFIER);

await expectRevert(
(gasOptions) => service.deployTokenManager(salt, '', LOCK_UNLOCK, params, 0, gasOptions),
service,
'NotSupported',
);

await expect(service.removeTrustedAddress(chainName)).to.emit(service, 'TrustedAddressRemoved').withArgs(chainName);
});
});

describe('Initialize remote custom token manager deployment', () => {
Expand Down Expand Up @@ -1153,6 +1169,34 @@ describe('Interchain Token Service', () => {

await service.setPauseStatus(false).then((tx) => tx.wait);
});

it('Should revert with NotSupported on deploying a remote custom token manager via its hub', async () => {
const salt = getRandomBytes32();

await (
await service.deployTokenManager(
salt,
'',
MINT_BURN,
defaultAbiCoder.encode(['bytes', 'address'], ['0x', wallet.address]),
0,
)
).wait();

const params = '0x1234';
const type = LOCK_UNLOCK;
const destinationChainItsHub = 'hub chain 1';

await expect(service.setTrustedAddress(destinationChainItsHub, ITS_HUB_ROUTING_IDENTIFIER))
.to.emit(service, 'TrustedAddressSet')
.withArgs(destinationChainItsHub, ITS_HUB_ROUTING_IDENTIFIER);

await expectRevert(
(gasOptions) => service.deployTokenManager(salt, destinationChainItsHub, type, params, gasValue, gasOptions),
service,
'NotSupported',
);
});
});

describe('Receive Remote Token Manager Deployment', () => {
Expand Down Expand Up @@ -2101,6 +2145,44 @@ describe('Interchain Token Service', () => {
);
});

it('Should revert with NotSupported when the message type is RECEIVE_FROM_HUB and has MESSAGE_TYPE_DEPLOY_TOKEN_MANAGER type.', async () => {
const salt = getRandomBytes32();

await (
await service.deployTokenManager(
salt,
'',
MINT_BURN,
defaultAbiCoder.encode(['bytes', 'address'], ['0x', wallet.address]),
0,
)
).wait();

const tokenId = await service.interchainTokenId(wallet.address, salt);
const params = '0x1234';
const type = LOCK_UNLOCK;
const sourceChain = 'hub chain 1';
const itsMessage = defaultAbiCoder.encode(
['uint256', 'bytes32', 'uint256', 'bytes'],
[MESSAGE_TYPE_DEPLOY_TOKEN_MANAGER, tokenId, type, params],
);
const payload = defaultAbiCoder.encode(
['uint256', 'string', 'bytes'],
[MESSAGE_TYPE_RECEIVE_FROM_HUB, sourceChain, itsMessage],
);
const commandId = await approveContractCall(gateway, ITS_HUB_CHAIN_NAME, ITS_HUB_ADDRESS, service.address, payload);

await expect(service.setTrustedAddress(sourceChain, ITS_HUB_ROUTING_IDENTIFIER))
.to.emit(service, 'TrustedAddressSet')
.withArgs(sourceChain, ITS_HUB_ROUTING_IDENTIFIER);

await expectRevert(
(gasOptions) => service.execute(commandId, ITS_HUB_CHAIN_NAME, ITS_HUB_ADDRESS, payload, gasOptions),
service,
'NotSupported',
);
});

it('Should revert with UntrustedChain when receiving a direct message from the ITS Hub. Not supported yet', async () => {
const data = '0x';
const payload = defaultAbiCoder.encode(['uint256', 'bytes'], [MESSAGE_TYPE_INTERCHAIN_TRANSFER, data]);
Expand Down

0 comments on commit 38698a2

Please sign in to comment.