xanoutas/solidity-security-findings huggingface dataset:
The source chain of Axelar-amplifier ITS does not have an initial balance, so all update_token_balance calls will be reverted 
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L101-L132
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/state.rs#L166-L196


# Vulnerability details

## Impact

The `ItsMessage::InterchainTransfer` call will not work.


## Proof of Concept

When `ExecuteMsg::Execute` is called in ITS `contract.rs`, `execute_message` in execute.rs will be called.

This `execute_message` function will call `apply_balance_tracking`

```
 match its_hub_message {
        ItsHubMessage::SendToHub {
            destination_chain,
            message: its_message,
        } => {
            apply_balance_tracking(
                deps.storage,
                source_chain.clone(),
                destination_chain.clone(),
                &its_message,
            )?;
```

If the message is an InterchainTransfer, `update_token_balance` will be called for the `source_chain` and the `destination_chain`. 

```
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())
            })?
        }
```

For the `source_chain`, the last parameter is set to false whereas the `destination_chain` last parameter is set to true. The last parameter refers to `is_deposit`.

```
pub fn update_token_balance(
    storage: &mut dyn Storage,
    token_id: TokenId,
>   chain: ChainName,
    amount: Uint256,
>   is_deposit: bool,
) -> Result<(), Error> {
    let key = TokenChainPair { token_id, chain };

  let token_balance = TOKEN_BALANCES.may_load(storage, key.clone())?;

    match token_balance {
        Some(TokenBalance::Tracked(balance)) => {
            let token_balance = if is_deposit {
                balance
>                   .checked_add(amount)
                    .map_err(|_| Error::MissingConfig)?
            } else {
                balance
>                   .checked_sub(amount)
                    .map_err(|_| Error::MissingConfig)?
            }
            .then(TokenBalance::Tracked);

            TOKEN_BALANCES.save(storage, key.clone(), &token_balance)?;
        }
        Some(_) | None => (),
    }
```

The `TO
Deploying an interchain token and a token manager for a token on a chain will always fail due to balance tracking error
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L43-L48
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L135-L142
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/state.rs#L159-L162


# Vulnerability details

When the ITS Hub receives an ITS message to process, it always calls the `apply_balance_tracking` function to either track or initiate tracking of the token balance on a chain based on the `ItsMessage`. For both `ItsMessage::DeployInterchainToken` and `ItsMessage::DeployTokenManager` messages, the function attempts to start balance tracking by calling `start_token_balance`. However, `start_token_balance` will fail if balance tracking has already been initiated. Consider the following scenario:

1. The ITS Hub receives an `ItsMessage::DeployInterchainToken` message. The Hub initiates balance tracking and sets it to `TokenBalance::Tracked(Uint256::zero())`.
2. Subsequently, the ITS Hub receives an `ItsMessage::DeployTokenManager` message to deploy a token manager for the already deployed interchain token. 

In this scenario, step 2 will always fail because the ITS Hub attempts to initiate balance tracking by setting it to `TokenBalance::Untracked` (as tracking is unnecessary when a token manager is present). However, since balance tracking was already initiated in step 1, the `start_token_balance` function will return an error.

## Impact
Deploying a token manager for an interchain token, or vice versa, will always fail in the ITS Hub. Having a token manager for an interchain token is a core functionality, and since the ITS Hub contract is a crucial component of a cross-chain ITS protocol, this issue severely impacts the overall functionality and reliability of the system.

## Proof of Concept
`apply_balance_tracking` is always called when the ITS Hub receives a message to process:
```rust
/// Executes an incoming ITS message.
///
/// This function handles the execution of ITS (Interchain Token Service) messages received from
/// trusted sources. It verifies the source address, decodes the message, applies balance tracking,
/// and forwards the message to the destination chain.
pub fn execute_message(
    deps: DepsMut,
    cc_id: CrossChainId,
    source_address: Address,
    payload: HexBinary,
) -> Result<Response, Error> {
    ...

    match its_hub_message {
        ItsHubMessage::SendToHub {
            destination_chain,
            message: its_message,
        } => {
@>          apply_balance_tracking(
@>              deps.storage,
@>              source_chain.clone(),
@>              destination_chain.clone(),
@>              &its_message,
@>          )?;

            ...
        }
        _ =
The hub does not protect ITS tokens that were not deployed on a compromised chain
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-amplifier/interchain-token-service/src/state.rs#L192


# Vulnerability details

## Impact
ITS hub tracks token balances so that a chain does not bridge out more than what was bridged in. However, the issue is that a chain could bridge out what was never deployed. 

A chain can have 3 possible values for TokenBalance 
* Tracked: when ITS token is deployed remotely
* Untracked: when TokenManager is deployed remotely
* None: when no remote is deployed

None means 2 things, not 1.
* It means the original chain (that hosts the original ITS token)
* It could also mean a strange chain. A strange chain is one that has neither the original nor a remote token.

When a chain is compromised, it cannot bridge out unlimited remote ITS tokens that were deployed because the balance is tracked. However, they can bridge out unlimited ITS tokens that were never deployed remotely because we return Ok() when the balance is None. This would be a lot of tokens on several chains. 

The compromised chain is pretending to own the original ITS token. This is very severe, especially considering that the main purpose of the hub and audit is to reduce damage to the wider ecosystem when a chain is compromised.


## Proof of Concept
Assuming, there are 2 ITS tokens that are native on Ethereum: TokenA and TokenB. And then
* TokenA was deployed remotely to MeowChain. TokenA balance would be tracked.
* 1,000 TokenA was sent from Ethereum to MeowChain
* MeowChain gets compromised

Let's compare 2 scenarios.
* MeowChain tries to send 1,001 TokenA to Ethereum
* Hub::update_token_balance would return an error and block the message
* This is good. The damage is contained

Vs

* MeowChain tries to send 1,000,000,000 TokenB to Ethereum
* Hub::update_token_balance would return Ok()
* 1,000,000,000 TokenB would be minted on Ethereum
* Repeat for every undeployed token from every other chain
* This is bad, the whole system could crumble

A compromised chain cannot exit its ITS tokens, but can still exit across all remaining ITS tokens. This would mean a lot of ITS tokens would be at risk. The more risky a chain is or the less popular it is, the fewer tokens would be deployed remotely, and therefore the more valuable tokens would be at risk during a compromise.

For example, MeowChain is a new amplifier chain that is not popular and has only 2 remote ITS tokens. One from Ethereum, and one from Arbitrum. If MeowChain gets compromised, those 2 ITS tokens would be protected. But, every other ITS token on Ethereum and Arbitrum and every other connected chain--which could be thousands of distinct tokens that are worth billions of dollars--is now at risk.

Examples of a compromise that could happen include
* Bad precompiles or revert handling: [Godwoken](https://medium.com/risk-dao/how-i-could-drain-an-entire-blockchain-post-mortem-on-a-bug-in-godwoken-chain-2451f83f72d2), [evmos](https://www.asymmetric.re/blog/
An attacker could deploy a gateway token and use it to drain the token on ITS.
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenService.sol#L286-L311
https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenFactory.sol#L301-L309
https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L114


# Vulnerability details

## Impact
An attacker could deploy a gateway token(TokenManagerType.GATEWAY) and use it to drain the token on ITS.

## Proof of Concept
Only owner is allowed to deploy `GATEWAY` token on `InterchainTokenFactory`

[InterchainTokenFactory.sol#L301-L309](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenFactory.sol#L301-L309)
```solidity
function registerGatewayToken(bytes32 tokenIdentifier, string calldata symbol) external onlyOwner returns (bytes32 tokenId) {
    address tokenAddress = gateway.tokenAddresses(symbol);
    if (tokenAddress == address(0)) revert NotGatewayToken(symbol);

    bytes memory params = abi.encode('', tokenAddress);
    bytes32 salt = gatewayTokenSalt(tokenIdentifier);

    tokenId = interchainTokenService.deployTokenManager(salt, '', TokenManagerType.GATEWAY, params, 0);
}
```
however user can deploy `GATEWAY` via [InterchainTokenService.deployTokenManager](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenService.sol#L286-L311)
```solidity
function deployTokenManager(
    bytes32 salt,
    string calldata destinationChain,
    TokenManagerType tokenManagerType,
    bytes calldata params,
    uint256 gasValue
) external payable whenNotPaused returns (bytes32 tokenId) {
    // 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;
    }

    tokenId = interchainTokenId(deployer, salt);

    emit InterchainTokenIdClaimed(tokenId, deployer, salt);

    if (bytes(destinationChain).length == 0) {
        _deployTokenManager(tokenId, tokenManagerType, params); <@
    } else {
        _deployRemoteTokenManager(tokenId, destinationChain, gasValue, tokenManagerType, params);
    }
}
```

An attacker could first deploy a `GATEWAY` token on `chain1`, and then deploy a `NATIVE_INTERCHAIN_TOKEN` on chain2. For this `NATIVE_INTERCHAIN_TOKEN`, the deployer can set a minter address and use it to mint tokens for themselves. The attacker can specify a token address that matches the legitimate gateway token. Finally, the attacker transfers the newly minted tokens to a remote chain that has the same gateway token. These newly minted tokens are then burned on the source chain, allowing the attacker to rec
Missing `chainId` in `TokenChainPair` Deserialization Causes Discrepancies in Token Balance Tracking and Message Execution in Rust Contract
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

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


# Vulnerability details

## Impact
In the `interchain-token-service` package's `state.rs` contract, the `TokenChainPair` struct's `KeyDeserialize` trait implementation incorrectly parses the length of `Vec<u8>` data. It only checks for the presence of the `tokenId` without verifying if the `chain` field exists. This oversight can lead to an empty `chain` being parsed into a `TokenChainPair` variant, which affects the contract's ability to accurately track and update on-chain token balances. Additionally, this issue can disrupt the execution of other contract-related messages.

## Proof of Concept
In the `interchain-token-service` package's `state.rs` contract, the `TokenChainPair` struct's `KeyDeserialize` trait is responsible for deserializing `Vec<u8>` data into a `TokenChainPair` struct. The struct contains two components: `tokenId` and `chain`. The `from_vec` method parses the first 32 bytes of `value` into the `tokenId`, and any remaining bytes are parsed into the `chain`. The issue arises because the `from_vec` method only checks if the length of the data is less than 32 (`if value.len() < 32`), which only ensures the presence of the `tokenId`. If `value.len() = 32`, the data can be parsed into a `tokenId` with an empty `chain`, affecting the functionality related to token balance tracking and updating. This, in turn, can impact the execution of other contract-related messages.
[axelar-amplifier/interchain-token-service/src/state.rs:KeyDeserialize_L71](https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/state.rs#L71)
```rust
impl KeyDeserialize for TokenChainPair {
    type Output = Self;

    fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
@audit=> if value.len() < 32 {
            return Err(StdError::generic_err("Invalid key length"));
        }
@audit=> let (token_id_bytes, chain_bytes) = value.split_at(32);
        let token_id = TokenId::new(
            token_id_bytes
                .try_into()
                .map_err(|_| StdError::generic_err("Invalid TokenId"))?,
        );
        let chain = ChainName::from_vec(chain_bytes.to_vec())?;

        Ok(TokenChainPair { token_id, chain })
    }
}

```

## Tools Used
Manual Review

## Recommended Mitigation Steps
It is recommended to modify the length check from `if value.len() < 32` to `if value.len() <= 32` to ensure that the data being deserialized into the `TokenChainPair` struct includes both the `tokenId` and the `chain`.


## Assessed type

Invalid Validation
expressExecute at the InterchainTokenService doesn't handle native tokens properly
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/InterchainTokenService.sol#L375
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/interchain-token-service/contracts/TokenHandler.sol#L177


# Vulnerability details

## Description
The `_contractCallValue` function's dev comments states the value is in terms of the native token if tokenAddress is zero:
```solidity
     * @dev If `tokenAddress` is `0`, then value is in terms of the native token, otherwise it's in terms of the token address.
```

If we take a look at the expressExecute function, there isn't a native transfer mechanism to handle such cases:
```solidity
function expressExecute(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload
    ) public payable whenNotPaused {
        ...
        _expressExecute(commandId, sourceChain, payload);
    }

function _expressExecute(bytes32 commandId, string calldata sourceChain, bytes calldata payload) internal {
        ...
            (bool success, bytes memory returnData) = tokenHandler.delegatecall(
                abi.encodeWithSelector(ITokenHandler.transferTokenFrom.selector, tokenId, msg.sender, destinationAddress, amount)
            );
            if (!success) revert TokenHandlerFailed(returnData);
            (amount, token) = abi.decode(returnData, (uint256, IERC20));
        }
		...
    }
```

TokenHandler's transferTokenFrom function doesn't provide any logic that can result in the transfer of  native tokens. Rather, the internal methods supposed to, treat the token as an ERC20:
```solidity
function _transferTokenFrom(address tokenAddress, address from, address to, uint256 amount) internal {
IERC20(tokenAddress).safeTransferFrom(from, to, amount);
    }

    function _transferToken(address tokenAddress, address to, uint256 amount) internal {
        IERC20(tokenAddress).safeTransfer(to, amount);
    }
```
## Impact
Native tokens are not possible to be executed, even if there is a willing party to call it.
The transfers will revert when attempting to call ERC20 methods on address zero.
## Tools Used
Manual review
## Recommended Mitigation Steps
Make sure to create a separate logic to handle the case in which users opt to bridge native tokens.  


## Assessed type

ETH-Transfer
Incorrect Type Conversion in `abi_decode` Method for `token_manager_type` in the `abi.rs` contract of `interchain-token-service` package
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/abi.rs#L161
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/abi.rs#L168


# Vulnerability details

## Impact
The `abi_decode` method in the `interchain-token-service` package incorrectly converts the `token_manager_type` field in the `DeployTokenManager` struct to a `u8` type instead of a `uint256`, causing decoding issues and preventing smart contracts from properly accessing the `token_manager_type`.

## Proof of Concept
In the `interchain-token-service` package, the `abi_decode` method is responsible for decoding the struct types of `ItsMessage` enum, including the `DeployTokenManager` struct. However, during the decoding process, the `token_manager_type` field is being converted to a `u8` type instead of the expected `uint256` format. This mismatch in data type conversion leads to incorrect decoding results, making it impossible for the smart contract to correctly interpret the `token_manager_type`.
[axelar-amplifier/interchain-token-service/src/abi.rs:ItsMessage.abi_decode_L161](https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/abi.rs#L161)
[axelar-amplifier/interchain-token-service/src/abi.rs:ItsMessage.abi_decode_L168](https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/abi.rs#L168)

```rust
    pub fn abi_decode(payload: &[u8]) -> Result<Self, Report<Error>> {
        if payload.len() < 32 {
            return Err(Report::new(Error::InvalidMessage));
        }

        let message_type = MessageType::abi_decode(&payload[0..32], true)
            .change_context(Error::InvalidMessageType)?;

        let message = match message_type {
            MessageType::InterchainTransfer => {
                let decoded = InterchainTransfer::abi_decode_params(payload, true)
                    .change_context(Error::InvalidMessage)?;

                Ok(ItsMessage::InterchainTransfer {
                    token_id: TokenId::new(decoded.tokenId.into()),
                    source_address: HexBinary::from(decoded.sourceAddress.to_vec()),
                    destination_address: HexBinary::from(decoded.destinationAddress.as_ref()),
                    amount: Uint256::from_le_bytes(decoded.amount.to_le_bytes()),
                    data: HexBinary::from(decoded.data.as_ref()),
                })
            }
            MessageType::DeployInterchainToken => {
                let decoded = DeployInterchainToken::abi_decode_params(payload, true)
                    .change_context(Error::InvalidMessage)?;

                Ok(ItsMessage::DeployInterchainToken {
                    token_id: TokenId::new(decoded.token