xanoutas/solidity-security-findings huggingface dataset:
Users can not register the canonical token as an interchain token in amplifier chains
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/InterchainTokenFactory.sol#L318


# Vulnerability details

## Impact

`AxelarAmplifierGateway` contract does not have `tokenAddresses` member.
As a result, users can not register the canonical token as an interchain token in amplifier chains.

## Proof of Concept

When users try to register a canonical token as an interchain token, it checks the token is gateway token from [L318](https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/InterchainTokenFactory.sol#L318).

```solidity
        function registerCanonicalInterchainToken(address tokenAddress) external payable returns (bytes32 tokenId) {
            bytes memory params = abi.encode('', tokenAddress);
L252:       if (_isGatewayToken(tokenAddress)) revert GatewayToken(tokenAddress);
            [...]
        }

        function _isGatewayToken(address token) internal view returns (bool) {
            string memory symbol = IInterchainToken(token).symbol();
L318:       return token == gateway.tokenAddresses(symbol);
        }
```

In amplifier chains, `gateway` varaible indicates the instance of `AxelarAmplifierGateway` contract and it does not have `tokenAddresses` member.

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/InterchainTokenService.sol#L139

```solidity
        constructor(
            address tokenManagerDeployer_,
            address interchainTokenDeployer_,
            address gateway_,
            address gasService_,
            address interchainTokenFactory_,
            string memory chainName_,
            address tokenManagerImplementation_,
            address tokenHandler_,
            address gatewayCaller_
        ) {
            [...]
L139:      gateway = IAxelarGateway(gateway_);
            [...]
        }
```

In `InterchainTokenService` contract, `gateway` is set from address variable `gateway_` from L139, and there is not compile error.

Thus, calling `gateway.tokenAddresses(symbol)` is reverted.
As a result, in amplifier chains, users can not register a canonical token as an interchain token.

## Tools Used

Manual review

## Recommended Mitigation Steps

It is recommended to add the external `tokenAddresses` function in `AxelarAmplifierGateway` contract.


## Assessed type

DoS
Interchain token transferring can be DoSed
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/InterchainTokenFactory.sol#L172


# Vulnerability details

## Impact

If malicious attacker's address on remote chain is same as interchain token deployer's address on source chain, the attacker can make token transferring DoSed.

## Proof of Concept

When deploying interchain tokens, `its_hub` does not track the balance of source chain.
If it tracks balance of source chain, transferring tokens from source chain to remote chain subtracts the transferring amount from source chain's tracking balance, but initial balance of source chain is zero.
Thus, token transferring is reverted by the underflow.
But, malicious attacker whose address on remote chain is same as token deployer's address on source chain can make the `its_hub` to track the balance of token's source chain.

Let's assume the following scenario:

- Alice deployed the tokenA into source chain A and remote chain B.
- Bob(malicious attacker)'s address on remote chain is same as Alice's address on source chain.
- Bob calls the `InterchainTokenFactory.deployRemoteInterchainToken` function with `originalChainName` parameter as chain A's name and `salt` parameter as the value which Alice used.

In this case, `its_hub` starts to track the `token_id`'s balance on chain A.

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L135C1-L138C10

```rust
        ItsMessage::DeployInterchainToken { token_id, .. } => {
            start_token_balance(storage, token_id.clone(), destination_chain.clone(), true)
                .change_context(Error::InvalidStoreAccess)?
        }
```

As a result, if users try to transfer tokenA from chain A to chain B, it will be reverted.
However, this vulnerbility is valid regardless of executing the Bob's message on destination chain.

## Tools Used

Manual review

## Recommended Mitigation Steps

In [`InterchainTokenFactory.deployRemoteInterchainToken`](https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/InterchainTokenFactory.sol#L172) function, remove the `originalChainName` parameter and use the `chainNameHash` to calculate `salt` instead of `chainNameHash_`.

```diff
    function deployRemoteInterchainToken(
-       string calldata originalChainName,
        bytes32 salt,
        address minter,
        string memory destinationChain,
        uint256 gasValue
    ) external 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 {
-
Can block bridge or limit the bridgeable amount by initializing the ITSHub balance of the original chain
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact

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.

## Proof of Concept

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.

```rust
fn apply_balance_tracking(
    storage: &mut dyn Storage,
    source_chain: ChainName,
    destination_chain: ChainName,
    message: &ItsMessage,
) -> Result<(), Error> {
    match message {
        ItsMessage::InterchainTransfer {
            token_id, amount, ..
        } => {
            // Update the balance on the source chain
@>          update_token_balance(
                storage,
                token_id.clone(),
                source_chain.clone(),
                *amount,
                false,
            )
@>          .change_context_lazy(|| Error::BalanceUpdateFailed(source_chain, token_id.clone()))?;

            // Update the balance on the destination chain
@>          update_token_balance(
                storage,
                token_id.clone(),
                destination_chain.clone(),
                *amount,
                true,
            )
@>          .change_context_lazy(|| {
                Error::BalanceUpdateFailed(destination_chain, token_id.clone())
            })?
        }
        // Start balance tracking for the token on the destination chain when a token deployment is seen
        // No invariants can be assumed on the source since the token might pre-exist on the source chain
        ItsMessage::DeployInterchainToken { token_id, .. } => {
@>          start_token_balance(storage, token_id.clone(), destination_chain.clone(), true)
                .change_context(Error::InvalidStoreAccess)?
        }
        ...
    };

    Ok(())
}
```

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.

```rust
pub fn start_token_balance(
    storage: &mut dyn Storage,
    token_id: TokenId,
    chain: ChainName,
    track_balance: bool,
)
`TokenHandler::_mintToken` and `_burnToken` Denial-of-Service Due to Wrong Access Control
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/69c4f2c3fcefb1b8eb2129af9c3685a44ae5b6fe/interchain-token-service/contracts/TokenHandler.sol#L164


# Vulnerability details


# [H-02] `TokenHandler::_mintToken` and `_burnToken` Denial-of-Service Due to Wrong Access Control
The internal functions `_mintToken` and `_burnToken` within the `TokenHandler` contract are designed to facilitate token creation or destruction by interacting with the `tokenManager`. These functions specifically target tokens of types `Burn/Mint`. However, the `tokenManager` imposes an `onlyService` modifier on its `mintToken` and `burnToken` functions, effectively blocking access to these functionalities unless the call originates from the designated service contract. This restriction results in a denial-of-service scenario, preventing any mint or burn transactions from proceeding.

```javascript
    function _mintToken(address tokenManager, address tokenAddress, address to, uint256 amount) internal {
        ITokenManager(tokenManager).mintToken(tokenAddress, to, amount);
    }

    function _burnToken(address tokenManager, address tokenAddress, address from, uint256 amount) internal {
        ITokenManager(tokenManager).burnToken(tokenAddress, from, amount);
    }
```
Below are the implementations of `mintToken` and `burnTokens` within the `tokenManager`:
```javascript
     * @notice External function to allow the service to mint tokens through the tokenManager
     * @dev This function should revert if called by anyone but the service.
     * @param tokenAddress_ The address of the token, since its cheaper to pass it in instead of reading it as the token manager.
     * @param to The recipient.
     * @param amount The amount to mint.
     */
    function mintToken(address tokenAddress_, address to, uint256 amount) external onlyService {
        IERC20(tokenAddress_).safeCall(abi.encodeWithSelector(IERC20MintableBurnable.mint.selector, to, amount));
    }

    /**
     * @notice External function to allow the service to burn tokens through the tokenManager
     * @dev This function should revert if called by anyone but the service.
     * @param tokenAddress_ The address of the token, since its cheaper to pass it in instead of reading it as the token manager.
     * @param from The address to burn the token from.
     * @param amount The amount to burn.
     */
    function burnToken(address tokenAddress_, address from, uint256 amount) external onlyService {
        IERC20(tokenAddress_).safeCall(abi.encodeWithSelector(IERC20MintableBurnable.burn.selector, from, amount));
    }
```
## Impact
The internal functions of the `TokenHandler` and external functions such as `takeToken`, which rely on these internal functions, become non-functional for `MINT_BURN_FROM` and `MINT_BURN` tokenManager types.

## Tools Used
Manual Review

## Recommended Mitigation Steps
To address this issue, it is recommended to either extend access rights to the `mintToken`
`TokenHandler::postTokenManagerDeploy` Denial-of-Service Due to Wrong Access Control
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/69c4f2c3fcefb1b8eb2129af9c3685a44ae5b6fe/interchain-token-service/contracts/TokenHandler.sol#L164


# Vulnerability details

# [H-01] `TokenHandler::postTokenManagerDeploy` Denial-of-Service Due to Wrong Access Control
The `postTokenManagerDeploy` function is utilized to prepare a token manager immediately after its deployment. It invokes the `tokenManager::approveService` method under the conditions where the tokenManager is of type `LOCK_UNLOCK` or `LOCK_UNLOCK_FEE`. However, the `approveService` function is exclusively callable through the `interchainTokenService` and is marked with the `onlyService` modifier. Consequently, the `postTokenManagerDeploy` function becomes ineffective due to its inability to access the `approveService` function.
```javascript
function postTokenManagerDeploy(uint256 tokenManagerType, address tokenManager) external payable {
@>      if (tokenManagerType == uint256(TokenManagerType.LOCK_UNLOCK) || tokenManagerType == uint256(TokenManagerType.LOCK_UNLOCK_FEE)) {
@>          ITokenManager(tokenManager).approveService();
@>      }

        // Approve the gateway here. One-time infinite approval works for gateway wrapped tokens, and for most origin tokens.
        // Approval can be refreshed in the future if needed for certain tokens via an upgrade, but realistically should never be exhausted.
        if (tokenManagerType == uint256(TokenManagerType.GATEWAY)) {
            address token = ITokenManager(tokenManager).tokenAddress();
            _approveGateway(token, UINT256_MAX);
        }
    }
```
```javacsript
@>  function approveService() external onlyService {
        /**
         * @dev Some tokens may not obey the infinite approval.
         * Even so, it is unexpected to run out of allowance in practice.
         * If needed, we can upgrade to allow replenishing the allowance in the future.
         */
        IERC20(this.tokenAddress()).safeCall(abi.encodeWithSelector(IERC20.approve.selector, interchainTokenService, UINT256_MAX));

    }
```
## Impact
The `postTokenManagerDeploy` function does not operate as intended, rendering the `tokenManager` incapable of granting approval to the `Service` contract.

## Proof of Concept
To illustrate this, append the following test to the `InterchainTokenServic.js::describe('Token Handler')` module, then execute it using `npx hardhat test --grep 'postTokenManagerDeploy function DOS'`:

```javascript
it('postTokenManagerDeploy function DOS', async () => {

            await expect(
                tokenHandler.postTokenManagerDeploy(2, tokenManager.address)
            ).to.be.revertedWithCustomError(tokenManager, 'NotService', [tokenHandler.address]);
            
        });
```
## Tools Used
Manual Review

## Recommended Mitigation Steps
It is advisable to either grant access to `approveService` to the `tokenHandler` or to relocate this function entirely to the service contract.






## Assessed t
FOT & Rebase tokens will not work
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/c383cc0e51805357bca8741ec5d1568cacbff6cc/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L101-L131


# Vulnerability details

As per the [README](https://code4rena.com/audits/2024-08-axelar-network), FOT & Rebase tokens are in scope, however, issues will arise whenever using these particular tokens. For example whenever using `apply_balance_tracking`:

```javascript
fn apply_balance_tracking(
    storage: &mut dyn Storage,
    source_chain: ChainName,
    destination_chain: ChainName,
    message: &ItsMessage,
) -> Result<(), Error> {
    match message {
        ItsMessage::InterchainTransfer {
->            token_id, amount, ..
        } => {
            // Update the balance on the source chain
            update_token_balance(
                storage,
                token_id.clone(),
                source_chain.clone(),
->                *amount,
                false,
            )
            .change_context_lazy(|| Error::BalanceUpdateFailed(source_chain, token_id.clone()))?;

            // Update the balance on the destination chain
            update_token_balance(
                storage,
                token_id.clone(),
                destination_chain.clone(),
->                *amount,
                true,
            )
            .change_context_lazy(|| {
                Error::BalanceUpdateFailed(destination_chain, token_id.clone())
            })?
        }
```

 When tokens are bridged from Chain A to Chain B, the `amount` is subtracted and added accordingly. However, if the token undergoes a rebase during this process, the rebase will not be reflected on the destination chain, effectively causing the rebased amount to be lost.

The same applies to FOT tokens, which include fees within their `amount` when, for example, bridging. This leads to inaccurate balance tracking.

### Recommendation
Introduce the logic to handle these type of tokens


## Assessed type

Oracle
Some tokens cannot be bridged
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenFactory.sol#L198


# Vulnerability details


https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenFactory.sol#L198

## Impact
The `InterchainTokenFactory` contract relies on the `name()` function of external token contracts to retrieve the name of the token when deploying or interacting with interchain tokens. If the external token contract's `name()` function is manipulated or not implemented correctly, it can return unexpected data types or invalid values. This can cause the `InterchainTokenFactory` to behave unpredictably, leading to potential deployment failures or registration of incorrect tokens. 

## Proof of Concept
Line 198 in `deployRemoteInterchainToken` function:

```javascript
InterchainTokenFactory.sol
172:     function deployRemoteInterchainToken(
173:         string calldata originalChainName,
174:         bytes32 salt,
175:         address minter,
176:         string memory destinationChain,
177:         uint256 gasValue
178:     ) external payable returns (bytes32 tokenId) {
179:         string memory tokenName;
180:         string memory tokenSymbol;
181:         uint8 tokenDecimals;
182:         bytes memory minter_ = new bytes(0);
183: 
184:         {
185:             bytes32 chainNameHash_;
186:             if (bytes(originalChainName).length == 0) {
187:                 chainNameHash_ = chainNameHash;
188:             } else {
189:                 chainNameHash_ = keccak256(bytes(originalChainName));
190:             }
191: 
192:             address sender = msg.sender;
193:             salt = interchainTokenSalt(chainNameHash_, sender, salt);
194:             tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);
195: 
196:             IInterchainToken token = IInterchainToken(interchainTokenService.interchainTokenAddress(tokenId));
197: 
198: -->         tokenName = token.name(); // Assumes that the name is a string.
199:             tokenSymbol = token.symbol();
200:             tokenDecimals = token.decimals();
201: 
202:             if (minter != address(0)) {
203:                 if (!token.isMinter(minter)) revert NotMinter(minter);
204: 
205:                 minter_ = minter.toBytes();
206:             }
207:         }
208: 
209:         tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, minter_, gasValue);
210:     }
```

Metadata are defined as optional in the [`ERC-20`](https://eips.ethereum.org/EIPS/eip-20#name) standards. Additionally, some tokens such as [`MKR`](https://etherscan.io/address/0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2#readContract) do not follow the standard and return their `name` and `symbol` as a `bytes32` instead of a `string`. 

The current implementation would revert and prevent such `ERC-20` tokens from being bridged. Moreover, tok
Potential loss of gas fees when `transmitInterchainTransfer` is called
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenService.sol#L527-L551


# Vulnerability details

https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenService.sol#L527-L551

## Impact
Lack of estimated `msg.value` in `transmitInterchainTransfer` function can lead to transaction failures and potentially lost gas fees. The function relies on the assumption that `msg.value` provided by the caller will be sufficient to cover the `gasValue` required for cross-chain transactions. However, if `msg.value` is insufficient, the transaction may revert unexpectedly.


## Proof of Concept
The `transmitInterchainTransfer` function calls the `_transmitInterchainTransfer` function, which in turn invokes the `_callContract` function. Within `_callContract`, the `gatewayCaller` function is used to initiate a cross-chain transaction. This function includes the `gasValue` parameter, which represents the amount of gas to be paid for the cross-chain message. The `msg.value` must be equal or greater than `gasValue` for the transaction to proceed as intended.

However, the code does not explicitly check if `msg.value` is equal or less than the required gas fee, leading to potential issues if the provided `msg.value` is insufficient.

## Code References:
`transmitInterchainTransfer` function calls `_transmitInterchainTransfer`

```javascript
    function transmitInterchainTransfer(
       . . .
    ) external payable whenNotPaused {
        string memory symbol;
        (amount, symbol) = _takeToken(tokenId, sourceAddress, amount, true);

        (IGatewayCaller.MetadataVersion metadataVersion, bytes memory data) = _decodeMetadata(metadata);

        _transmitInterchainTransfer(
            tokenId,
            sourceAddress,
            destinationChain,
            destinationAddress,
            amount,
            metadataVersion,
            data,
            symbol,
@>          msg.value
        );
    }
```

`_transmitInterchainTransfer` function calls `_callContract`/`_callContractWithToken` with `gasValue`

```javascript
    function _transmitInterchainTransfer(
        . . .
    ) internal {
        if (amount == 0) revert ZeroAmount();

        // slither-disable-next-line reentrancy-events
        emit InterchainTransfer(
            tokenId,
            sourceAddress,
            destinationChain,
            destinationAddress,
            amount,
            data.length == 0 ? bytes32(0) : keccak256(data)
        );

        bytes memory payload = abi.encode(
            MESSAGE_TYPE_INTERCHAIN_TRANSFER,
            tokenId,
            sourceAddress.toBytes(),
            destinationAddress,
            amount,
            data
        );
        if (bytes(symbol).length > 0) {
@>          _callContractWithToken(destinationChain, payload, symbol, amount, metadataVersion, gasValue);
        } else {
@>          _callC