Submitted by klau5
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/InterchainTokenFactory.sol#L176
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/InterchainTokenService.sol#L342
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/InterchainTokenFactory.sol#L269
Token deployers can block the token bridge or limit the bridgeable amount without having Operator or FlowLimiter permissions. Especially, Canonical tokens can be attacked by anyone, not just the token register.
ITSHub does not track the balance of the token on the original chain. It only tracks the balance of other chains which is deployed by remote deployment. This is because on the original chain, minters are usually registered to allow token minting, making balance tracking difficult.
The balance of token on destination chain is initialized to 0 only when a new token is remotely deployed. And when tokens move, only the balance of the chain where the balance data has been initialized is updated. In normal cases, the balance of the original chain is not tracked.
However, there is a way to initialize the ITSHub balance of the original chain. When initializing the balance, it is set to 0, not the actual amount of tokens minted on the original chain. Therefore, if the balance of the original chain is initialized, the ITSHub.update_token_balance will fail due to underflow, making it impossible to send tokens from the original chain to other chains or limiting the amount that can be bridged.
You can initialize the ITSHub balance of the source chain because the destinationChain parameter in InterchainTokenFactory.deployRemoteInterchainToken does not be checked if it is the source chain of the token. The same issue exists when directly calling InterchainTokenService.deployInterchainToken to deploy tokens. This allows token deployment requests from remote chains to the original chain with the same tokenId.
While the token with the tokenId already exists on the original chain, its possible to approve the GMP to the original chain, but the transaction will be failed when executed. However, the ITSHub balance initialization occurs during the process of transmitting the GMP to the destination chain, so it doesnt matter if the transaction fails on the original chain. Moreover, the initialized balance is not deleted even if the GMP execution fails.
The same issue occurs when deploying a canonical interchain token through InterchainTokenFactory.deployRemoteCanonicalInterchainToken, and it has the most critical severity. The tokenId of the canonical token is determined by the address of the original token, and the callers address does not affect it. Therefore, anyone can call InterchainTokenFactory.deployRemoteCanonicalInterchainToken to deploy a specific canonical interchain token. This means anyone can prevent a specific canonical token from being bridged out from the original chain. Since a canonical token can only be registered once, this token can no longer be used normally with the Axelar bridge.
Lets look at an example of what happens when you initialize the ITSHub balance of the original chain. Suppose there are chains A, B, and C, where A is the original chain, and B and C are related chains. Here are the ITSHub balances:
Now, using the vulnerability, the balance on chain A has been initialized.
Until chain B or C send some tokens to chain A, no more tokens can be go out from chain A. Also, only a maximum of 150 tokens can move between bridges.
This is a PoC. You can run it by adding it to interchain-token-service/test/InterchainTokenService.js. It shows that chain A is the original chain, and after remotely deploying a token from A to B, its possible to request remote deployment from B to A. On chain A, a token with the same tokenId is already deployed, so the GMP execution on the chain A will be failed, but the balance of chain A in ITSHub will be initialized to 0.
Invalid Validation
milapsheth (Axelar) confirmed and commented:
0xsomeone (judge) commented:
milapsheth (Axelar) commented:
0xsomeone (judge) commented:
