xanoutas/solidity-security-findings huggingface dataset:
`takeToken` will revert with some tokens
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/TokenHandler.sol#L113


# Vulnerability details

## Impact
With some tokens [takeToken](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L91-L123) will revert, preventing them from being bridged.

## Proof of Concept
[takeToken](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L91-L123) is used by token service to pull tokens from users before they are bridged. That function will revert with some tokens because it tries to assign `.symbol()` to a string value, but some tokens like [MKR](https://github.com/d-xo/weird-erc20?tab=readme-ov-file#non-string-metadata) use bytes as their name and symbol.

```solidity
    } else if (tokenManagerType == uint256(TokenManagerType.GATEWAY)) {
        symbol = IERC20Named(tokenAddress).symbol();
        _transferTokenFrom(tokenAddress, from, address(this), amount);
```

This will cause [takeToken](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L91-L123) to revert, which in tern reverts the bridging TX.

## Tools Used
Manual review.

## Recommended Mitigation Steps
Handle the name as bytes, or use a try/catch.


## Assessed type

Error
Message execution may be skipped at the destination chain by front running the validation in gateway
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-gmp-sdk-solidity/contracts/gateway/BaseAmplifierGateway.sol#L87-L95
https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-gmp-sdk-solidity/contracts/gateway/BaseAmplifierGateway.sol#L129-L136


# Vulnerability details

## Impact
The approved message at the destination chain may be skipped for execution by maliciously front running the validation which can be called by anyone and make the status of message as executed.

## Proof of Concept
After an interchain message is initiated at the source chain, the message will be process and signed by validators. Once the threshold of signatures is reached, relayer can call `AxelarAmplifierGateway.approveMessages()` at the destination chain to make it ready for execution. The actual execution will call `validateContractCall()` or `validateMessage()` to check if the message is approved by validators and mark it as executed. However, these two function do not have any access control. Malicious actor can front run the call for these two functions and the status will be changed as executed but no actual execution was taken.

## Tools Used
Manually review

## Recommended Mitigation Steps


## Assessed type

DoS
EXECUTED state update is not necessarily accurate
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/69c4f2c3fcefb1b8eb2129af9c3685a44ae5b6fe/axelar-amplifier/contracts/axelarnet-gateway/src/contract/execute.rs#L111-L145


# Vulnerability details

### Description
Whenever messages need to be executed, the `execute` function is invoked. Inside this function, the `update_msg_status` method is called to transition the state of `msgs` from `APPROVED` to `EXECUTED`:

```javascript
pub(crate) fn execute(
    store: &mut dyn Storage,
    api: &dyn Api,
    querier: QuerierWrapper,
    cc_id: CrossChainId,
    payload: HexBinary,
) -> Result<Response, Error> {
===>    let msg = state::update_msg_status(store, cc_id.clone())
           .change_context(Error::MessageStatusUpdateFailed(cc_id))?;
```

Following this, the function carries out some additional checks until it reaches the end, where it processes the messages by invoking the `add_message` method and subsequently, an event is emitted that displays the messages to be executed

```javascript
    // Call the destination contract
    // Apps are required to expose AxelarExecutableMsg::Execute interface
    Ok(Response::new()
===>        .add_message(executable.execute(msg.cc_id.clone(), msg.source_address.clone(), payload))
===>        .add_event(AxelarnetGatewayEvent::MessageExecuted { msg }.into()))
}
```

The `add_message` function is responsible for pushing the now `EXECUTED` messages into a list of messages to be processed:

```javascript
 /// This creates a "fire and forget" message, by using `SubMsg::new()` to wrap it,
    /// and adds it to the list of messages to process.
    pub fn add_message(mut self, msg: impl Into<CosmosMsg<T>>) -> Self {
        self.messages.push(SubMsg::new(msg));
        self
    }
```

There is a discrepancy, however, between message status and actual processing. Messages are labeled as `EXECUTED` while still pending in the processing queue. As per the [Axelar Docs](https://docs.axelar.dev/dev/general-message-passing/monitoring):  `EXECUTED: informs the executed result whether it is successful or not.` In reality, messages marked as `EXECUTED` may still be awaiting processing and are therefore not finalised. 

As for the event, it will emit a `MessageExecuted` event, even though the message might still be in the processing phase and, in some cases, could remain stuck for a while. Despite this, the event will still indicate that the message has been executed.

As per the [README](https://code4rena.com/audits/2024-08-axelar-network#top):

```
- Does the message validation function accurately validate messages and update their status?
```

We believe our finding showcases that the message validation can reflect an incorrect status. 
### Recommendation
We recommend introducing logic that accurately reflects the state of a message when it is still in processing mode.


## Assessed type

Other
`contractCallWithTokenValue` will be unusable
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Vulnerability details
The purpose of the `contractCallWithTokenValue` function is: `Returns the amount of token that this call is worth`. The issue is that in order for a user to get the amount, they are looking for, they need to supply the same amount. This is contradictory to the entire purpose of the function and users will be unable to get the value they are looking for.

This function is important as stated by the protocol team: `These functions are queried by the express relayer to determine the value of the ITS call. They are not the main focus of the audit but support the relayer in processing transactions.` Therefore, the express relayer will be hurdled in determining the value of an ITS contract call with token.

## Impact
Due to issues in the logic of the `contractCallWithTokenValue` function, it will be practically unusable.

## Proof of Concept
As we can see in the code, `contractCallWithTokenValue` makes a call to `_checkPayloadAgainstGatewayData`:

```solidity
function contractCallWithTokenValue(
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount
    ) public view virtual onlyRemoteService(sourceChain, sourceAddress) whenNotPaused returns (address, uint256) {
        _checkPayloadAgainstGatewayData(payload, symbol, amount);
        return _contractCallValue(payload);
    }
```

This is problematic, as `_checkPayloadAgainstGatewayData` requires the caller to supply `amount` as a parameter. The `amount` that the user needs to supply is the same as the `amount` that they are querying the function for, contradictory to the purpose of the function.

## Tools Used
Manual review

## Recommended Mitigation Steps
The `_checkPayloadAgainstGatewayData` in `contractCallWithTokenValue` is practically not needed and can be omitted.








## Assessed type

Other
Inconsistent Minter Assignment and Flow Limiter Settings in `InterchainTokenFactory::deployInterchainToken()`
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details


## Description

The `InterchainTokenFactory` contract contains a critical function [`deployInterchainToken()`](https://github.com/code-423n4/2024-08-axelar-network/blob/69c4f2c3fcefb1b8eb2129af9c3685a44ae5b6fe/interchain-token-service/contracts/InterchainTokenFactory.sol#L126-L161) responsible for deploying new interchain tokens. This function handles the initial setup of the token, including assigning the minter and configuring flow limiter settings. However, the current implementation has a logical flaw that can lead to inconsistent token management.

The function takes several parameters, including `initialSupply` and `minter`. The issue arises from the conditional execution of minter assignment and flow limiter configuration based solely on the `initialSupply` value. Specifically:

1. If `initialSupply > 0`, the contract sets itself as the initial minter, mints tokens, transfers mintership, and configures flow limiters.
2. If `initialSupply == 0`, regardless of the `minter` parameter, no minter assignment or flow limiter configuration occurs.

This logic creates a scenario where a token can be deployed with a specified `minter`, but the minter is not actually assigned if `initialSupply` is zero. The relevant code snippet is:

```solidity
File: InterchainTokenFactory.sol
146:         if (initialSupply > 0) {
147:             IInterchainToken token = IInterchainToken(interchainTokenService.interchainTokenAddress(tokenId));
148:             ITokenManager tokenManager = ITokenManager(interchainTokenService.tokenManagerAddress(tokenId));
149: 
150:             token.mint(sender, initialSupply);
151: 
152:             token.transferMintership(minter);
153:             tokenManager.removeFlowLimiter(address(this));
154: 
155:             // If minter == address(0), we still set it as a flow limiter for consistency with the remote token manager.
156:             tokenManager.addFlowLimiter(minter);
157: 
158:             tokenManager.transferOperatorship(minter);
159:         }

```

This inconsistency can lead to tokens being deployed without proper minter assignment or flow limiter settings, potentially compromising the intended token management structure.

## Impact

The inconsistent handling of minter assignment and flow limiter settings can lead to several issues:

- Tokens deployed with zero initial supply will lack proper minter assignment, potentially rendering them unmanageable or requiring additional transactions to set up correctly.
- Flow limiter settings will not be configured for tokens with zero initial supply, which could lead to unexpected behavior in token transfers or other operations that rely on these settings.


## Proof of Concept

1. Alice calls `deployInterchainToken()` with the following parameters:
   - `initial
Migration will not be possible due to no admin set in `instantiate()`
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/contracts/axelarnet-gateway/src/contract.rs#L63-L85


# Vulnerability details

## Description
The Axelarnet Gateway contract is initliazed by calling `instantiate()`:
```rust
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
    deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    msg: InstantiateMsg,
) -> Result<Response, axelar_wasm_std::error::ContractError> {
    cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

    let router = deps
        .api
        .addr_validate(&msg.router_address)
        .change_context(Error::InvalidAddress(msg.router_address.clone()))?;

    let config = Config {
        chain_name: msg.chain_name,
        router,
    };

    state::save_config(deps.storage, &config).change_context(Error::InvalidStoreAccess)?;

    Ok(Response::new())
}
```

If we take a look at the [Cosmwasm docs](https://docs.cosmwasm.com/docs/smart-contracts/migration), we can find the following:
```md
CosmWasm made contract migration a first-class experience. 
When instantiating a contract, there is an optional admin field that you can set. 
If it is left empty, the contract is immutable. 
If it is set (to an external account or governance contract), that account can trigger a migration. 
The admin can also change admin or even make the contract fully immutable after some time. 
However, when we wish to migrate from contract A to contract B, contract B needs to be aware somehow of how the state was encoded.
```

In the `instantiate()` function shown above, there is no `admin` field set. This means that this contract is immutable and contrary to the intention of the Sponsor, `migrate()` will not be callable:
```rust
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(
    deps: DepsMut,
    _env: Env,
    _msg: Empty,
) -> Result<Response, axelar_wasm_std::error::ContractError> {
    cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

    Ok(Response::default())
}
```

This results in a non-upgradeable contract, even though it should be upgradeable, breaking one of the invariants set in the `README.md`.

## Tools Used
Manual Review

## Recommended Mitigation Steps
Set the admin field.


## Assessed type

Other
Trusted addresses can not be removed
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Description
In `interchain-token-service/src/state.rs`, the following function is meant to remove trusted addresses:
```rust
#[cfg(test)]
pub(crate) fn remove_trusted_address(
    storage: &mut dyn Storage,
    chain: &ChainName,
) -> Result<(), Error> {
    TRUSTED_ITS_ADDRESSES.remove(storage, chain);
    Ok(())
}
```

The problem is, as we can see in the code snippet, is that the `#[cfg(test)]` flag is used.

If we take a look at the [Rust Book](https://doc.rust-lang.org/book/ch11-03-test-organization.html#the-tests-module-and-cfgtest), we can read the following:
```
The `#[cfg(test)]` annotation on the tests module tells Rust to compile and run the test code only when you run `cargo test`, not when you run `cargo build`. This saves compile time when you only want to build the library and saves space in the resulting compiled artifact because the tests are not included.
```

This means during the `cargo build` run, it will **not** include the `remove_trusted_address()` function.

This means if any of the current trusted addresses go rogue, they won't be able to be removed because the `remove_trusted_address()` function is not included in the release binary.

## Tools Used
Manual Review

## Recommended Mitigation Steps
Remove  `#[cfg(test)]`:
```diff
- #[cfg(test)]
pub(crate) fn remove_trusted_address(
    storage: &mut dyn Storage,
    chain: &ChainName,
) -> Result<(), Error> {
    TRUSTED_ITS_ADDRESSES.remove(storage, chain);
    Ok(())
}
```


## Assessed type

Other
Express executors may execute invalid commands, losing their transferred funds
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Vulnerability details
`expressExecute` is intended to be called by an Express Relayer, that charges fees for express executing. The issue is that malicious users can transfer tokens from a chain with a valid token manager to a different chain where there is no token manager deployed, connected to the original `tokenId`. As a result, the Express Relayer will express execute the transfer, transferring funds to the destination address with the expectation of receiving those funds at a later time. However, they will be unable to get back their funds, as the required token manager will not have been deployed on the destination chain.

## Impact
As a result, malicious users will be able to grief the Express Relayer, causing a great loss of funds.


## Proof of Concept
When `interchainTransfer` is called there is no way to know whether a token manager, corresponding to the `tokenId`, has been deployed on the destination chain:
```solidity
function interchainTransfer(
        bytes32 tokenId,
        string calldata destinationChain,
        bytes calldata destinationAddress,
        uint256 amount,
        bytes calldata metadata,
        uint256 gasValue
    ) external payable whenNotPaused {
        string memory symbol;
        (amount, symbol) = _takeToken(tokenId, msg.sender, amount, false);

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

        _transmitInterchainTransfer(
            tokenId,
            msg.sender,
            destinationChain,
            destinationAddress,
            amount,
            metadataVersion,
            data,
            symbol,
            gasValue
        );
    }
```

This leaves the Express Relayer vulnerable to losing funds as `expressExecute` will not fail even if there is not a deployed token manager:
```solidity
 function _expressExecute(bytes32 commandId, string calldata sourceChain, bytes calldata payload) internal {
        (, bytes32 tokenId, bytes memory sourceAddress, bytes memory destinationAddressBytes, uint256 amount, bytes memory data) = abi
            .decode(payload, (uint256, bytes32, bytes, bytes, uint256, bytes));
        address destinationAddress = destinationAddressBytes.toAddress();

        IERC20 token;
        {
            (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));
        }

        // slither-disable-next-line reentrancy-events
        emit InterchainTransferReceived(
            commandId,
            t
Stuck tokens cannot be recovered
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Vulnerability details
Currently, in order for tokens to be transferred from one chain to another they first need to be locked/burnt on the source chain and then unlocked/minted on the destination chain. The issue is that there are several cases where the tokens will not be able to be recovered on the destination chain, causing a loss of funds for users.

## Impact
Due to the lack of a recovery function for stuck funds, users may suffer a loss of their bridged funds.

## Proof of Concept
Here are the possible scenarios where recovering tokens on the destination chain will be impossible:

1/ If the `flowLimit` becomes less than the transferred funds, before the token bridge has been executed on the destination chain, the initiator of the token transfer will not be able to recover their funds on the destination chain. The only way for this to happen would be if the `flowLimit` is increased to a value higher than the amount of tokens. This may not occur, as it will be fully dependent on the token manager operator, which may be malicious.

2/ If a `TokenManager`, corresponding to the source `tokenId`, has not been deployed on the destination chain it will be impossible for the tokens to be transferred to the destination address, as `TokenHandler.giveToken` will fail.

3/ If a destination chain changes or entirely removes another chain's trusted address, all pending transfers coming from that chain will not be executable. This will prevent users who have transferred tokens from the updated/removed chain and are yet to claim them, from ever retrieving their funds. 
This becomes much more dangerous as with the addition of the ITS Hub, many chains will change their `InterchainAddressTracker` configurations.

4/ There may not be enough locked tokens on the destination chain to transfer to the destination address. This will prevent the user from receiving their bridged tokens until more tokens are locked on the destination chain, which may never happen.

## Tools Used
Manual review

## Recommended Mitigation Steps
Add a recovery mechanism for stuck tokens on the source chain.














## Assessed type

Other
The Axelar Amplifier Gateway is Not Fully Backward Compatible
Audit: 2024-08-axelar-network-findings
Severity: MEDIUM

# Lines of code

https://github.com/axelarnetwork/interchain-token-service/blob/498a02b5ca59871e657b42871dba061796cf7860/contracts/InterchainTokenService.sol#L689-L699


# Vulnerability details


## Impact
A Denial of Service (DoS) will occur for all applications and users attempting to call `executeWithToken` on the ITS edge.

## Proof of Concept (PoC)
According to the documentation, the Axelar Amplifier Gateway is expected to be backward compatible with the standard Gateway.

```
The EVM Amplifier gateway also supports legacy methods for compatibility with the existing EVM AxelarExecutable contract. These aren't needed for gateway implementations for non-EVM chains.
```

[Source](https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-gmp-sdk-solidity/contracts/gateway/INTEGRATION.md#interface)

There are two methods to execute a message on the destination chain: `execute` and `executeWithTokens`. These methods require message validation before execution on the destination chain. This validation is performed by making a call to the `gateway` to obtain a boolean value indicating whether the message is valid.

The `executeWithTokens` function calls `validateContractCallAndMint`, which validates the message and mints a specific amount of tokens.

```solidity
function _executeWithToken(
    bytes32 commandId,
    string calldata sourceChain,
    string calldata sourceAddress,
    bytes memory payload,
    string calldata tokenSymbol,
    uint256 amount
) internal {
    bytes32 payloadHash = keccak256(payload);

    if (!gateway.validateContractCallAndMint(commandId, sourceChain, sourceAddress, payloadHash, tokenSymbol, amount))
        revert NotApprovedByGateway();
}
```

[Source](https://github.com/axelarnetwork/interchain-token-service/blob/498a02b5ca59871e657b42871dba061796cf7860/contracts/InterchainTokenService.sol#L923-L935)

However, the `validateContractCallAndMint` function is not implemented by the `AxelarAmplifierGateway`, which prevents the validation of `executeWithTokens` messages, despite the claim of backward compatibility.

The `AxelarAmplifierGateway` only implements the `validateContractCall` function, which is used by the `execute` method.

```solidity
function validateContractCall(
    bytes32 commandId,
    string calldata sourceChain,
    string calldata sourceAddress,
    bytes32 payloadHash
) external override returns (bool valid) {
    valid = _validateMessage(commandId, sourceChain, sourceAddress, payloadHash);
}
```

[Source](https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-gmp-sdk-solidity/contracts/gateway/BaseAmplifierGateway.sol#L129-L136)

So also the function `validateContractCallAndMint` should be implemented by the `axelarAmplifierGateway` .

for now , If the call is approved in the Axelar Amplifier Gateway, attempting to execute the message on the ITS edge will always result in failure.

## Recommendations
The Axelar Gateway contract should i