xanoutas/solidity-security-findings huggingface dataset:
`expressReceiveToken` can be abused using reentry
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L487


# Vulnerability details

## Description
A token transfer can be express delivered on behalf of another user, also when the call contains data to be executed:

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L487
```solidity
File: its/interchain-token-service/InterchainTokenService.sol

467:    function expressReceiveTokenWithData(
		    // ... params
475:    ) external {
476:        if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);
477:
478:        address caller = msg.sender;
479:        ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
480:        IERC20 token = IERC20(tokenManager.tokenAddress());
481:
482:        SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);
483:
484:        _expressExecuteWithInterchainTokenToken(tokenId, destinationAddress, sourceChain, sourceAddress, data, amount);
485:
486:        _setExpressReceiveTokenWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, caller);
487:    }
```

The issue here is that check effects interactions is not followed.

There are a two of attack paths here with varying assumptions and originating parties:

### Attacker: Anyone, assuming there are third parties providing `expressReceiveTokenWithData` on demand with on-chain call
1. An attacker sends a large token transfer to a chain with a public mempool.

2. Once the attacker sees the call by Axelar to [`AxelarGateway::exectute`](https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/cgp/AxelarGateway.sol#L323) in the mempool they front run this call with a call to the third party providing `expressReceiveTokenWithData`.

3. The third party (victim) transfers the tokens to the `destinationAddress` contract. Attacker is now `+amount` from this transfer.

4. `expressExecuteWithInterchainToken` on the `destinationAddress` contract does a call to `AxelarGateway::exectute` (which can be called by anyone) to submit the report and then a reentry call to `InterchainTokenService::execute` their `commandId`. This performs the second transfer from the `TokenManager` to the `destinationAddress` (since the `_setExpressReceiveTokenWithData` has not yet been called). Attacker contract is now `+2x amount`, having received both the express transfer and the original transfer.

5. `_setExpressReceiveTokenWithData` is set but this `commandId` has already been executed. The victims funds has been stolen.

### AxelarGateway operator, assuming there are third parties providing `expressReceiveTokenWithData` off-chain.
The operator does the same large transfer as described above. The operator then holds the update to `AxelarGateway::execute` and instead sends these instructions to their malicious `destinat
ERC777 and similar token implementations allow stealing of funds when transferring tokens
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L82-L85
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L48-L51


# Vulnerability details

## Impact
A malicious actor can trick a `TokenManager` into thinking that a bigger amount of tokens was transferred. On the destination chain, the malicious actor will be able to receive more tokens than they sent on the source chain.
## Proof of Concept
[TokenManagerLockUnlock](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L16) and [TokenManagerLiquidityPool](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L17) are `TokenManager` implementations that transfer tokens from/to users when sending tokens cross-chain. The low-level `_takeToken` function ([TokenManagerLiquidityPool._takeToken](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L77), [TokenManagerLockUnlock._takeToken](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/implementations/TokenManagerLockUnlock.sol#L44)) is used to take tokens from a user on the source chain before emitting a cross-chain message, e.g. via the [TokenManager.sendToken](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/TokenManager.sol#L83) function. The function computes the difference in the balance of the liquidity pool or the token manager before and after the transfer, to track the actual amount of tokens transferred. The amount is then [passed in the cross-chain message](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/TokenManager.sol#L90-L99) to tell the `InterchainTokenService` contract on the destination chain [how much tokens to give to the recipient](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L610).

The `_takeToken` function, however, is not protected from re-entrancies, which opens up the following attack scenario:
1. A malicious contract initiates transferring of 100 ERC777 tokens by calling [TokenManager.sendToken](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/TokenManager.sol#L83).
1. The `_takeToken` function calls `transferFrom` on the ERC777 token contract, which calls the [tokensToSe
Colluded signers can steal native coins from a signer
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/cgp/governance/AxelarServiceGovernance.sol#L52
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/cgp/auth/MultisigBase.sol#L58-L63


# Vulnerability details

## Impact
Colluded signers can steal the native coins deposited by another signer to execute a proposal.
## Proof of Concept
The [AxelarServiceGovernance.executeMultisigProposal](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/cgp/governance/AxelarServiceGovernance.sol#L48) function allows signers to execute cross-chain governance proposals. A proposal may require some amount of the native coin to be executed (the amount is set by the [nativeValue](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/cgp/governance/InterchainGovernance.sol#L71) argument), thus the function as the `payable` modifier.

Signers approve a proposal by calling the `executeMultisigProposal` function with the parameters of the proposal. The [onlySigners](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/cgp/auth/MultisigBase.sol#L44) modifier collects signer's votes until the total number of votes reaches the threshold. A proposal is executed [after the threshold is reached](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/cgp/auth/MultisigBase.sol#L58-L76). Thus, a proposal is executed by the last signer.

However, the `onlySigners` modifier allows any signer to deposit the native coins required to execute a proposal. This allows a scenario when:
1. a signer votes for a proposal they created and deposits native coins in the call;
1. the other signers don't vote for the proposal, execute [rotateSigners](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/cgp/auth/MultisigBase.sol#L142) to remove the signer from the list of signers and execute another proposal that transfer the deposited native coins to the address of the signers.

Basically, this allows colluded signers to steal funds from a victim signer. Since the `AxelarServiceGovernance` contract is meant to be a general solution for different projects and groups of people to execute cross-chain governance solutions (i.e. signers are not trusted by the protocol), malicious behaviour of signers is possible. For example:
1. a protocol may submit a proposal that deposits a big amount of native coins to a third-party protocol;
1. the signer who initiated the proposal votes for it and deposits the coins;
1. the other signers collude, remove the signer, and execute a different proposal that transfers the coins to their address.

Another scenario that can happen is that voting becomes stale and doesn't reach the threshold after one of the signers has vote
Owner can override InterchainTokenService addresses
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L83-L89


# Vulnerability details

## Impact

The `addTrustedAddress` function does not check if the address of the InterchainTokenService passed as a parameter already exists and assigns a new one to the desired chain. if the InterchainTokenService already exists it will cause problems since it will reset it.

## Proof of Concept

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L83-L89

```solidity
    function addTrustedAddress(string memory chain, string memory addr) public onlyOwner {
        if (bytes(chain).length == 0) revert ZeroStringLength();
        if (bytes(addr).length == 0) revert ZeroStringLength();
        remoteAddressHashes[chain] = keccak256(bytes(_lowerCase(addr)));
        remoteAddresses[chain] = addr;
        emit TrustedAddressAdded(chain, addr);
    }

  in this function it's only checked if the `addr` is not empty but not checked if it already exists, the owner can override it by mistake without any problems.
```


## Tools Used
Manual review

## Recommended Mitigation Steps
Add a check to see if the InterchainTokenService being assigned already exists and reverts or at least add a two step action if overriding it's what is intended.


## Assessed type

Invalid Validation
Signers funds will be stuck in Multisig
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/cgp/governance/Multisig.sol#L30-L36
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/cgp/governance/AxelarServiceGovernance.sol#L48-L62


# Vulnerability details

## Impact
The Multisig contract's `execute` function allows signers to call any function on any external contract if the threshold number of signers trigger the method with the same args. But if the `Vote count < threshold` and a signer call it with `msg.value > 0 `, the funds will anyway go to Multisig without calling the function on the external contract. The same impact applies on `AxelarServiceGovernance#executeMultisigProposal` .

## Proof of Concept
The POC test is made using Foundry. to integrate it follow the instructions [here](https://hardhat.org/hardhat-runner/docs/advanced/hardhat-and-foundry) .
the test file should be created in the test Folder : **test/MultisigTest.t.sol**

 run : 
- `forge build`
- `forge test -m testExecute`

```
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "contracts/cgp/governance/Multisig.sol";

contract MultisigTest is Test {
    Multisig public multisig;
    address[] public accounts;

    address signer1;
    address signer2;
    uint256 public threshold;

    function setUp() public {
        signer1 = makeAddr("signer1");
        signer2 = makeAddr("signer2");

        accounts.push(signer1);
        accounts.push(signer2);

        threshold = 2;

        multisig = new Multisig(accounts, threshold); // create the Multisig contract
    }

    function testExecute() public {
        vm.deal(signer1, 1 ether); // signer1 has now 1 ether .

        address target = address(0);
        bytes memory callData;
        uint256 nativeValue = 1 ether;

        vm.prank(signer1);
        multisig.execute{value: 1 ether}(target, callData, nativeValue); // signer1 calls execute with 1 ether .

        // funds are transfered to multisig even if the call to external contract is not executed .
        assertEq(address(multisig).balance, 1 ether);
        assertEq(signer1.balance, 0);
    }
}
```
- create a Multisig contract with two signers accounts, and threshold == 2 .
- fund signer1 with 1 ether .
- singer1 calls execute with his 1 ether .
- we notice that funds are transferred to Multisig but the call is not executed only one singer called it but two are needed .
- there is no way signer can get his funds back .

## Tools Used
Foundry, VS code .
## Recommended Mitigation Steps
in `onlySigners` modifier if (voteCount < signers.threshold) resend back funds to `msg.sender` .


## Assessed type

Payable
Frontrun attack executing same transaction twice
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/cgp/auth/MultisigBase.sol#L44


# Vulnerability details

## Impact
Same transaction can be executed twice by using transactions meant for only one instance.

## Proof of Concept
Even if there is one malicious signer for 2/3 signer multisig, he can pick transactions from mempool and execute transactions twice for 
``` 
function execute(address target,
        bytes calldata callData,
        uint256 nativeValue);
```

Let's say in 2/3 multisig, there is transaction which need to be executed. User1 and User2 both sent their transaction to execute it, the malicious user make two identical transactions and bundle them as:
[User 1 tx, Malicious User Tx1, User2 tx, Malicious User Tx2] thereby executing same action twice which can lead to loss of funds


## Tools Used
VS Code
## Recommended Mitigation Steps
Have a nonce field as well in function to avoid usage of mempool transactions


## Assessed type

MEV
Potential Denial of Service and Front-running Vulnerability in expressReceiveToken and expressReceiveTokenWithData Functions
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L439-L454
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L487


# Vulnerability details

## Impact
The `expressReceiveToken` and `expressReceiveTokenWithData` functions in the contract accept a `commandId` parameter, which could correspond to an initiated but not yet executed command. Each `commandId` should be unique throughout the system. Once a command is executed, its `commandId` is marked as executed, and cannot be executed again.

## Proof of Concept
[contracts/its/interchain-token-service/InterchainTokenService.sol#L439-L454](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L439-L454)
```
    function expressReceiveToken(
        bytes32 tokenId,
        address destinationAddress,
        uint256 amount,
        bytes32 commandId
    ) external {
        if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);

        address caller = msg.sender;
        ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
        IERC20 token = IERC20(tokenManager.tokenAddress());

        SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);

        _setExpressReceiveToken(tokenId, destinationAddress, amount, commandId, caller);
    }
```

[contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L487](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L467-L487)

```
    function expressReceiveTokenWithData(
        bytes32 tokenId,
        string memory sourceChain,
        bytes memory sourceAddress,
        address destinationAddress,
        uint256 amount,
        bytes calldata data,
        bytes32 commandId
    ) external {
        if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId);

        address caller = msg.sender;
        ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenId));
        IERC20 token = IERC20(tokenManager.tokenAddress());

        SafeTokenTransferFrom.safeTransferFrom(token, caller, destinationAddress, amount);

        _expressExecuteWithInterchainTokenToken(tokenId, destinationAddress, sourceChain, sourceAddress, data, amount);

        _setExpressReceiveTokenWithData(tokenId, sourceChain, sourceAddress, destinationAddress, amount, data, commandId, caller);
    }
```
A Denial of Service (DoS) attack might occur in this context if a malicious user tries to execute these functions prematurely with the same `commandId`. Within `expressReceiveToken` and `expressReceiveTokenWithData`, there'
Malicious users can DOS the deployment of remote token manager by frontrun and steal cross-chain funds
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L666
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L678


# Vulnerability details

## Impact

InterchainTokenService supports cross-chain message execution to deploy the appropriate token manager.
However, the token manager and standardizedToken deployed salt parameter through create3 are not comprehensive, which depends only on the `tokenId`.
A malicious user can DOS the deployment of the same tokenId by modifying other parameters, resulting in the deployment of a different type of token manager and standardizedToken.
Further, because it is an asynchronous cross-chain message, if users only look at whether the contract is deployed at the corresponding address, the user may mistakenly think that the contract is deployed with the correct parameters and conduct subsequent interactions. But it is actually a contract deployed by a malicious user frontrun with malicious parameters, which may cause a loss of user funds.

## Proof of Concept

```solidity
    function _processDeployTokenManagerPayload(bytes calldata payload) internal {
        (, bytes32 tokenId, TokenManagerType tokenManagerType, bytes memory params) = abi.decode(
            payload,
            (uint256, bytes32, TokenManagerType, bytes)
        );
        _deployTokenManager(tokenId, tokenManagerType, params);
    }

    function _processDeployStandardizedTokenAndManagerPayload(bytes calldata payload) internal {
        (
            ,
            bytes32 tokenId,
            string memory name,
            string memory symbol,
            uint8 decimals,
            bytes memory distributorBytes,
            bytes memory operatorBytes
        ) = abi.decode(payload, (uint256, bytes32, string, string, uint8, bytes, bytes));
        address tokenAddress = getStandardizedTokenAddress(tokenId);
        address tokenManagerAddress = getTokenManagerAddress(tokenId);
        address distributor = distributorBytes.length > 0 ? distributorBytes.toAddress() : tokenManagerAddress;
        _deployStandardizedToken(tokenId, distributor, name, symbol, decimals, 0, distributor);
        TokenManagerType tokenManagerType = distributor == tokenManagerAddress ? TokenManagerType.MINT_BURN : TokenManagerType.LOCK_UNLOCK;
        _deployTokenManager(
            tokenId,
            tokenManagerType,
            abi.encode(operatorBytes.length == 0 ? address(this).toBytes() : operatorBytes, tokenAddress)
        );
    }

    function deployTokenManager(
        bytes32 tokenId,
        uint256 implementationType,
        bytes calldata params
    ) external payable {
        bytes memory args = abi.encode(address(this), implementationType, tokenId, params);
        bytes memory bytecode = abi.encodePacked(type(TokenManage
Deployer of standardized token is allowed to deploy same standardized token to another chain, with different decimals
Audit: 2023-07-axelar-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L421


# Vulnerability details

## Impact
Deployer of a Standardized token is allowed to remotely deploy a standardized token to another chain with different decimals.
When this happens, interchain transfer will cause many users to be greatly cheated.

## Proof of Concept
Here is the function used to remotely deploy a standardized token to another chain:

```solidity
function deployAndRegisterRemoteStandardizedToken(
    bytes32 salt,
    string calldata name,
    string calldata symbol,
@>  uint8 decimals,
    bytes memory distributor,
    bytes memory operator,
    string calldata destinationChain,
    uint256 gasValue
) external payable notPaused {
    bytes32 tokenId = getCustomTokenId(msg.sender, salt);
    _deployRemoteStandardizedToken(tokenId, name, symbol, decimals, distributor, operator, destinationChain, gasValue);
}
```

As we can see, deployer is allowed to specify the standardized token's decimals again. This could lead to the following scenario:

-   Alice deploys a standardized token(STAND) on Ethereum through `deployAndRegisterStandardizedToken`, with 18 decimals
-   After some time(when STAND token has circulated and gained value to an extent), Alice remotely deploys STAND token to Arbitrum using `deployAndRegisterRemoteStandardizedToken`, specifying 8 decimals
-   If a user makes an interchain transfer of 1 STAND from Ethereum to Arbitrum, he gets minted 10^(18-8) STANDs on Arbitrum
-   User will then make an interchain transfer of 10^10 STANDs back to Ethereum.
-   Now, user has gained 10^10 STANDs from an interchain transfer of just 1 STAND
-   This would affect all other holders of STAND token on Ethereum because the value of their tokens will be drastically reduced due to inflation.

This bug manifests when a tokenId has different decimal values across chains. So instead of `deployAndRegisterRemoteStandardizedToken`, deployer can cause same effect by calling `deployAndRegisterStandardizedToken` on each chain with unequal decimals

## Tools Used
Manual Review
## Recommended Mitigation Steps
It is essential that a tokenId has equal metadata(especially decimals) across all chains.
Consider implementing these:

-   don't allow remote deployment of a standardized token, when deployer has not deployed a standardized token with that tokenId on the source chain.
-   deployAndRegisterRemoteStandardizedToken for a tokenId should use the exact same metadata as the standardized token already deployed on that source chain.
-   Axelar gateway should keep track of unique tokenids across chains, and should prevent a deployer from calling `deployAndRegisterStandardizedToken` on a tokenId that exists on another chain. Deployers must use `deployAndRegisterRemoteStandardizedToken`(from source chain where they deployed the first standardized token), to deploy standardized tokens with that tokenId to other cha