xanoutas/solidity-security-findings huggingface dataset:
Anyone can call function setup() in TokenManager.sol through the TokenManagerProxy contract
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/token-manager/TokenManager.sol#L101


# Vulnerability details

## Impact
Function setup() in TokenManager.sol can be called again through the TokenManagerProxy contract's fallback function. This occurs since the setup() function only applies the onlyProxy() modifier and not the onlyOwner() as well. 

Due to this, any malicious actor can call the function setup() through the TokenManagerProxy contract to set a another address as the FLOW_LIMITER and OPERATOR. This allows the address to change the flow limit values to a small amount to DOS interchain transfers occurring through ITS for that specific interchain token as well as provides access to the transferFlowLimiter(), addFlowLimiter() and removeFlowLimiter() functions in TokenManager.sol to take over the interchain token and remove the current operator and flow limiter addresses as well as the ITS contract to DOS interchain transfer calls. 

Note, a similar instance also exists in the AxelarAmplifierGateway.sol contract, where the AxelarAmplifierGatewayProxy inherits the Proxy.sol contract which inherits the BaseProxy contract with the fallback function. Since anyone can call the setup() function through the proxy on the AxelarAmplifierGateway implementation contract, it would allow rotating signers without any delay to malicious signer addresses. This would allow forging and approving malicious messages. The solution suggested in this report needs to be applied to the internal setup() function in AxelarAmplifierGateway as well.

## Proof of Concept

1. Attacker calls the fallback function on the TokenManagerProxy.sol contract, which is present in the inherited BaseProxy.sol contract. The calldata passed would be setup() function selector with the bytes parameter containing the malicious operator address.

```solidity
    fallback() external payable virtual {
        address implementation_ = implementation();
        assembly {
            calldatacopy(0, 0, calldatasize())

            let result := delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())

            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }
```

2. This delegatecalls to the setup() function in the TokenManager.sol implementation contract. The setup() function has an onlyProxy() modifier that ensures the call only occurs from the proxy contract. But the function does not restrict the msg.sender to be the owner of the contract with onlyOwner() modifier.

```solidity
function setup(bytes calldata params_) external override(Implementation, IImplementation) onlyProxy {
        bytes memory operatorBytes = abi.decode(params_, (bytes));

        address operator = address(0);
Bridge requests to remote chains where interchain tokens are not deployed can result in DoS attacks
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#L112-L135
https://github.com/code-423n4/2024-08-axelar-network/blob/4572617124bed39add9025317d2c326acfef29f1/axelar-amplifier/interchain-token-service/src/state.rs#L192


# Vulnerability details

## Impact

Insufficient balance in the ITSHub prevents bridging, leading to a DoS attack on the bridge.

## Proof of Concept

ITSHub tracks token balances per chain when moving tokens. If the interchain token is not deployed on the destination chain, the balance is uninitialized, and this transaction is not reverted but passed. In other words, token transfer requests are processed normally even if the interchain token is not deployed on the destination chain.

```rust
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 => (),
    }

    Ok(())
}
```

If the interchain token is not deployed on the destination chain, even if the message is approved, tokens cannot be bridged because the token is not deployed. However, we can consider scenarios where the remote interchain token deployment request is frontruned. For canonical tokens, anyone can deploy remote interchain tokens, so it's easy to create a scenario where token transfer is requested first, followed by a request to deploy the remote interchain token.

Consider the following example:

1. The token deployer requests remote interchain token deployment to chain B. This will be frontruned.
2. Front-running (1), a request is made to transfer 100 ether of tokens.
3. ITSHub first executes `ItsMessage::InterchainTransfer`. As the interchain token is not yet deployed on chain B, the balance for chain B remains `None`.
4. ITSHub then processes `ItsMessage::DeployInterchainToken`, initializing the balance of chain B to 0.
5. After the remote interchain token deployment is completed on chain B, the attacker executes `execute` to receive the bridged tokens.

The balance in ITSHub is 0, but there are 100 ether of bridged tokens on chain B. This balance mismatch can cause problems such as DoS. For example, if another user bridges tokens from chain A to B, in
Operators can remove ITS Edge as Operator and block interchain transfers by setting flow limit to 1
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/utils/FlowLimit.sol#L94-L140
https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L120
https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L51
https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/token-manager/TokenManager.sol#L101-L115
https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/token-manager/TokenManager.sol#L149-L151


# Vulnerability details

When a Token Manager is deployed, the deployer can [set an Operator](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/token-manager/TokenManager.sol#L112) for it. This operator 
can [remove](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/token-manager/TokenManager.sol#L149-L151) the flow-limiter apart from other functions it can run. 

The operator is also a flow limiter that can set limits for transfer amounts during interchain transfers. When the flow limit is configured to 0, no limit is applied to outflows or inflows of tokens. 

ref: [FlowLimit._addFlowOut()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/utils/FlowLimit.sol#L116-L125)
```solidity
function _addFlowOut(uint256 flowOutAmount_) internal {
    uint256 flowLimit_ = flowLimit();
    if (flowLimit_ == 0) return;
    // ... snip ...
}
```

ref: [FlowLimit._addFlowIn()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/utils/FlowLimit.sol#L131-L140)
```solidity
function _addFlowIn(uint256 flowInAmount_) internal {
    uint256 flowLimit_ = flowLimit();
    if (flowLimit_ == 0) return;
    // ... snip ...
}
```

If the flow-limit is set to 1, any interchain transfer of tokens greater than 1 will revert.

ref: [FlowLimit._addFlow()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/utils/FlowLimit.sol#L105)
```solidity
if (flowAmount > flowLimit_) revert FlowLimitExceeded(flowLimit_, flowAmount, address(this));
```

## Impact
The Operator can set the flow limit to 1 and block interchain transfers. This prevents users from withdrawing their locked tokens from paired remote Token Managers of the affected Interchain Token. This is a direct loss of funds for victim users.

## Proof of Concept
Consider the following scenario:

1. A Native Interchain Token with tokenId 23 has been deployed in Chain A. It has Alice set as its Operator.
2. Alice removes the ITS Edge contract as Flow Limiter for the Interchain Token. 
3. The Interchain Token 23 has a paired remote LOCK_UNLOCK Token Manager in Chain B. 
4. Users have transferred tokens of tokenId 23 from Chain B to Chain A and th
cUSDCv3 as a canonical token can be drained from ITS Edge because of how it handles uint256 on transfers
Audit: 2024-08-axelar-network-findings
Severity: HIGH

# Lines of code

https://github.com/compound-finance/comet/blob/main/contracts/Comet.sol#L981-L983
https://github.com/compound-finance/comet/blob/main/contracts/Comet.sol#L945-L948


# Vulnerability details

Compound III's cUSDCv3 token has special-case handling of transferring a maxUint256 amount.

ref: [Comet::transferInternal()](https://github.com/compound-finance/comet/blob/main/contracts/Comet.sol#L981-L984)
```solidity
  if (amount == type(uint256).max) {
      amount = balanceOf(src);
  }
  return transferBase(src, dst, amount);
```

Instead of failing since the sender does not have enough balance, the transfer amount is converted to the total balance of the sender. This behavior in cUSDCv3 can be abused when it is [registered](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenFactory.sol#L249-L256) as a canonical interchain token. 

Canonical Interchain Tokens always have a LOCK_UNLOCK Token Manager. LOCK_UNLOCK Token Managers do not update the amount in the payload to the actual amount received when taking tokens from the sender.

ref: [TokenHandler::takeToken()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L108-L111)
```solidity
} else if (tokenManagerType == uint256(TokenManagerType.LOCK_UNLOCK)) {
    _transferTokenFrom(tokenAddress, from, tokenManager, amount);
} else if (tokenManagerType == uint256(TokenManagerType.LOCK_UNLOCK_FEE)) {
    // This type of Token Manager will modify the amount based on the actual amount received by the TokenManager from the sender
    amount = _transferTokenFromWithFee(tokenAddress, from, tokenManager, amount);
```

## Impact
Direct loss of funds for any user that gets their cUSDCv3 locked in the Token Manager when they do interchain transfers with the canonical interchain token for cUSDCv3.

## Proof of Concept

Consider the following scenario:

1. cUSDCv3 is registered as a canonical interchain token (tokenId 23) in Chain A and a paired remote canonical interchain token has been deployed for it in Chain B. 
2. Alice has a balance of 1 cUSDCv3 and starts an interchain transfer of maxUint256 tokens of tokenId 23 from Chain A to Chain B with Alice as the recipient.
3. The interchain transfer [takes](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L109) 1 cUSDCv3 from Alice (because of cUSDCv3's special-case handling of maxUINT256) and locks it in the Token Manager in Chain A. However, the amount in the payload is still maxUint256.
This is because LOCK_UNLOCK Token Managers do not modify the amount based on the actual amount taken from the sender, unlike with [LOCK_UNLOCK_FEE Token Managers](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L110-L111).
5. In Chain B, the interchain transfer is approved and executed. This paired interchain token
Canonical Interchain Tokens can only be registered with LOCK_UNLOCK Token Managers
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/InterchainTokenFactory.sol#L245-L256


# Vulnerability details

When [registering](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenFactory.sol#L245-L256) a Canonical Interchain Token, the Token Manager's type is always set to `LOCK_UNLOCK`.

ref: [InterchainTokenFactory::registerCanonicalInterchainToken()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenFactory.sol#L255)
```
  // Can not set to LOCK_UNLOCK_FEE
  tokenId = interchainTokenService.deployTokenManager(salt, '', TokenManagerType.LOCK_UNLOCK, params, 0);
```

However, some pre-existing tokens can have transfer fees. The correct Token Manager type for these tokens is the `LOCK_UNLOCK_FEE`.

## Impact
All interchain transfers done with fee-on-transfer tokens that are registered canonical interchain tokens will not account for the transfer fees. Recipients of the transfers receive the full amount even though transfer fees are deducted. The ITS Edge locks up fewer tokens than are sent to recipients.

This leads to insolvency since recipients always hold more tokens than the ITS Edge. When all holders of the remote interchain tokens withdraw to the source chain, there will not be enough locked tokens to handle the withdrawals.

## Proof of Concept
Consider the following scenario:

1. Token A is a fee-on-transfer token registered as a canonical interchain token in Chain A. It is paired with a remote native interchain token in Chain B.
2. Alice sends 100 tokens of Token A from Chain A to B. 
3. The ITS Edge locks only 98 tokens because a transfer fee of 2% was applied when the tokens were transferred from Alice to the ITS Edge.
4. The Interchain Transfer is approved and executed in Chain B, where Bob, the recipient, gets 100 tokens instead of 98.
5. Bob eventually sends the 100 tokens of Token A back to Chain A, the source chain with the canonical interchain token. This burns Bob's 100 tokens.
6. In Chain A, the interchain transfer of 100 tokens is approved and executed. However, execution fails since the ITS Edge only holds 98 tokens.

Bob's 100 tokens are burned and irrecoverable. 

## Tools Used
Manual Review, Test

## Recommended Mitigation Steps
Consider allowing registration of LOCK_UNLOCK_FEE canonical interchain tokens. 



## Assessed type

Other
Anyone can steal locked tokens in the ITS Edge by deploying a Gateway Token Manager for the target token
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/TokenHandler.sol#L112-L115
https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L73-L76
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/proxies/TokenManagerProxy.sol#L45


# Vulnerability details

When the ITS Edge does Interchain Transfers of Gateway Tokens, it [takes tokens](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L114) from the sender and keeps them in the ITS Edge. 

ref: [TokenHandler::takeToken()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/TokenHandler.sol#L112-L115)
```solidity
// `address(this)` here is the ITS Edge contract
_transferTokenFrom(tokenAddress, from, address(this), amount);
```

These Gateway Tokens kept in the ITS Edge can be stolen by anyone because:
1. All Gateway Token Managers will lock their tokens in the ITS Edge when processing interchain transfers. This differs from other Interchain Tokens where the tokens are either burned or locked in their respective Token Managers.
2. Multiple Gateway Token Managers can handle the same underlying token. Token Managers can be [deployed](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenService.sol#L286-L311) by anyone. For example, if a Token Manager exists for USDC, another user can deploy another Gateway Token Manager for USDC.

Any tokens locked in an ITS Edge can be stolen by the attacker deploying a Gateway Token Manager for the [target token](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/InterchainTokenService.sol#L290). The attacker can then pair it with a remote Native Interchain Token where they are the minter.

ref: [TokenManagerProxy::constructor()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/proxies/TokenManagerProxy.sol#L45)
```solidity
// The `tokenAddress` comes from the user-specified `params`.
tokenAddress = IBaseTokenManager(implementation_).getTokenAddressFromParams(params);
```

The user can specify the deployment `params` [here](https://github.com/code-423n4/2024-08-axelar-network/blob/main/interchain-token-service/contracts/proxies/TokenManagerProxy.sol#L45). The params include the `tokenAddress`.
This allows any deployer to target any token locked in the ITS Edge.

The attacker will then mint themselves Interchain Tokens and transfer these to the target ITS Edge where they have their paired Gateway Token Manager. 
Once the interchain transfer is processed in the destination ITS Edge, locked target tokens in th
Anyone can front-run an Interchain Token Deployment with Interchain Transfers to mess up ITS Hub's balance tracking
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#L150
https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L108-L138
https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L108-L138


# Vulnerability details

The ITS Hub [tracks balances](https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L133-L138) of Native Interchain Tokens. This balance tracking only starts once a Native Interchain Token is deployed.

ref: [interchain-token-service/src/contract/execute.rs::apply_balance_tracking()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L133-L138)
```rust
// 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)?
}
```

When Interchain Transfers are processed, the ITS Hub [udpates](https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-amplifier/interchain-token-service/src/contract/execute.rs#L111-L128) the Native Interchain Token's total balance based on the amount withdrawn or deposited. However, if the Native Interchain Token has not yet been deployed, there is no balance tracking. Any balance changes caused by Interchain Transfers for that not-yet-deployed Native Interchain Token will not be tracked. 

This issue can be abused by frontrunning Interchain Token Deployments with Interchain Transfers for the token whose deployment is currently in progress.

## Impact
The ITS Hub has the following balances tracked:
- Chain A - untracked
- Chain B - 1000

If an attacker sneaks in 1000 untracked Tokens into Chain B with the described issue, the ITS Hub's balance tracking for Chain B is off by 1000.

When the attacker withdraws the 1000 untracked Tokens from Chain B, Chain B's balance will be updated to 0 in the ITS Hub. This prevents other users from withdrawing 1000 tokens from Chain B because the ITS Hub [prevents withdrawing](https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-amplifier/interchain-token-service/src/state.rs#L183-L187) more funds than is available in its balance tracking.

ref: [interchain-token-service/src/state.rs::update_token_balance()](https://github.com/code-423n4/2024-08-axelar-network/blob/main/axelar-amplifier/interchain-token-service/src/state.rs#L183-L187) 
```rust
    // @audit this will fail the transaction on underflow
    balance
        .checked_sub(amount)
        .map_err(|_
Executing express operations do not check the gas payment for express call
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


# Vulnerability details

## Impact

Users can execute express operations by paying gas for contract call instead of paying gas for express call.

## Proof of Concept

The `InterchainTokenService.expressExecute` does not check whether the message creator pays the gas for express call.
As a result, users can execute mssages using express service without paying gas for express call.

Let's consider the following scenario:

- Alice calls `InterchainTokenService.interchainTransfer` function with `MetadataVersion.CONTRACT_CALL` parameter on source chain.
- She calls `InterchainTokenService.expressExecute` function by paying transferring amount of tokens on destination chain.
- After the message approved, she calls `InterchainTokenService.execute` to get the payed tokens.
Totally, message was executed in express mode without gas payment for express call.

## Tools Used

Manual review

## Recommended Mitigation Steps

It is recommended to add the mechanism to check `MetadataVersion` of the message when trying to execute express operations on destination chain.


## Assessed type

Other