xanoutas/solidity-security-findings huggingface dataset:
CENTRALIZATION RISK IN THE CRITICAL FUNCTIONS OF THE `InterchainProposalExecutor` CONTRACT
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L92-L99
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L107-L114


# Vulnerability details

## Impact

The `InterchainProposalExecutor.setWhitelistedProposalCaller` and `InterchainProposalExecutor.setWhitelistedProposalSender` are critical functions of the `InterchainProposalGovernance` system. Both these functions are controlled by the `onlyOwner` modifier. Hence the `deployer` of the contract has a huge authority over the `InterchainProposalExecutor` contract, since he can decide which proposal senders and proposal callers to whitelist.

If the `owner` private key is `compromised`, or the owner turns `malicious` the attacker can completely lock the `InterchainProposalExecutor` contract execution by changing the `whitelistedCallers[sourceChain][sourceCaller]` and `whitelistedSenders[sourceChain][sourceSender]` mapping, `Boolean` value to `false` for each of the `sourceCaller` and `sourceSender`.

Hence this create a huge centralization risk for the smooth execution of the protocol.

## Proof of Concept

```solidity
    function setWhitelistedProposalCaller(
        string calldata sourceChain,
        address sourceCaller,
        bool whitelisted
    ) external override onlyOwner {
        whitelistedCallers[sourceChain][sourceCaller] = whitelisted;
        emit WhitelistedProposalCallerSet(sourceChain, sourceCaller, whitelisted);
    }
```

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L92-L99

```solidity
    function setWhitelistedProposalSender(
        string calldata sourceChain,
        address sourceSender,
        bool whitelisted
    ) external override onlyOwner {
        whitelistedSenders[sourceChain][sourceSender] = whitelisted;
        emit WhitelistedProposalSenderSet(sourceChain, sourceSender, whitelisted);
    }
```

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/interchain-governance-executor/InterchainProposalExecutor.sol#L107-L114

## Tools Used
Manual Review and VSCode

## Recommended Mitigation Steps

Hence it is recommended to implement a `multisig` as the owner of the `InterchainProposalExecutor` so a single `owner` will not be able to break the contract.


## Assessed type

Other
Compromised Distributor and Operator accounts could destabllize and halt functioning of the protocol
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-implementations/StandardizedToken.sol#L76
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-implementations/StandardizedToken.sol#L86
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/TokenManager.sol#L171
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L534
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/token-manager/implementations/TokenManagerLiquidityPool.sol#L67


# Vulnerability details

## Vulnerability details
If the private keys of the Distributor and/or Operator get compromised, it can destabilize and halt the protocol since they have control over important config settings of the protocol such as flow in and flow out limits, setting the address of the liquidity pool, minting and burning tokens etc. This could be the impact on the protocol:

1. The changed flow in and flow out limits could lock a sender's ETH or allow overflowing the limit.
2. The changed malicious address will lock sender's tokens and allow the attacker to steal them if they are sent after the protocol is compromised.
3. Control over minting and burning could destabilize the price of a token.

## Tools Used
Manual Review

## Recommended Mitigation Steps
A multi-sig should be used for configuration operations like these in order to prevent losing control over the protocol.




## Assessed type

Access Control
The minimum time delay can be set to zero in the constructor
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/gmp-sdk/util/TimeLock.sol#L22


# Vulnerability details

## Impact
The minimum time delay can be set to zero in the constructor. That can cause each proposal to bypass the timelock.

## Proof of Concept
In case the `_minimumTimeLockDelay` immutable will be set to zero, a time delay parameter `eta` for proposals could be also set to zero: 
```solidity
21:    constructor(uint256 minimumTimeDelay) {
22:        _minimumTimeLockDelay = minimumTimeDelay;
23:    }

50:    function _scheduleTimeLock(bytes32 hash, uint256 eta) internal returns (uint256) {
51:        if (hash == 0) revert InvalidTimeLockHash();
52:        if (_getTimeLockEta(hash) != 0) revert TimeLockAlreadyScheduled();
53:
54:        uint256 minimumEta = block.timestamp + _minimumTimeLockDelay;
55:
56:        if (eta < minimumEta) eta = minimumEta;
57:
58:        _setTimeLockEta(hash, eta);
59:
60:        return eta;
61:    }
```
## Tools Used
Manual review
 
## Recommended Mitigation Steps
I suggest using zero check for the `minimumTimeDelay` constructor argument.



## Assessed type

Timing
Incorrect sender validation
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L72-L74
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L124
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L579


# Vulnerability details

## Proof of Concept

Below presents the `RemoteAddressValidator.validateSender()` function that can incorrectly validate a sender (`sourceAddress`).

If the `sourceAddress` parameter can be computed to match the `interchainTokenServiceAddressHash` immutable (the hash of the interchain token service address on the current chain), the validation will be valid without further verifying the `sourceChain` parameter.

Nevertheless, the `sourceChain` parameter can refer to another chain, which might finally refer to an unauthorized/invalid `sourceAddress`.

```solidity
    function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) {
        string memory sourceAddressLC = _lowerCase(sourceAddress);
        bytes32 sourceAddressHash = keccak256(bytes(sourceAddressLC));
@>      if (sourceAddressHash == interchainTokenServiceAddressHash) {
@>          return true;
@>      }
        return sourceAddressHash == remoteAddressHashes[sourceChain];
    }
```

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/remote-address-validator/RemoteAddressValidator.sol#L72-L74

## Impact

The `RemoteAddressValidator.validateSender()` function can incorrectly validate `sourceAddress`, resulting in broken access authorizations since the `validateSender()` will be executed by the [`InterchainTokenService.onlyRemoteService()`](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L124) modifier, which will finally be utilized by the [`InterchainTokenService._execute()`](https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/interchain-token-service/InterchainTokenService.sol#L579) function for executing on-chain/cross-chain interchain token services.

## Tools Used

Manual Review

## Recommended Mitigation Steps

I recommend always validating both the `sourceChain` and `sourceAddress` parameters as follows.

```solidity
    function validateSender(string calldata sourceChain, string calldata sourceAddress) external view returns (bool) {
        string memory sourceAddressLC = _lowerCase(sourceAddress);
        bytes32 sourceAddressHash = keccak256(bytes(sourceAddressLC));
@>      return sourceAddressHash == remoteAddressHashes[sourceChain];
    }
```


## Assessed type

Invalid Validation
USER FUNDS COULD BE LOST DUE TO REDUNDANT `metadata` INPUT VARIABLE
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/token-manager/TokenManager.sol#L83-L88
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/token-manager/TokenManager.sol#L92-L99
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/token-manager/TokenManager.sol#L136-L142
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/token-manager/TokenManager.sol##L145-L152
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L511
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L519-L520
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/interchain-token-service/InterchainTokenService.sol#L715-L721


# Vulnerability details

## Impact

In the `TokenManager.sendToken` and `TokenManager.transmitInterchainTransfer` functions are used to call the `interchainTokenService` contract for `token transfers` without passing any data. In these two functions there is an input parameter `metadata`. This parameter is passed into the `interchainTokenService.transmitSendToken` function.

But the `interchainTokenService.transmitSendToken` only uses this function to check whether the length of the `medtadata` is less than `4` to decide on the method to construct the `payload`. This is done as follows:

        if (metadata.length < 4) {

Now consider the following scenario:

1. A user decides to initiate a cross chain transfer of tokens without `data` and calls the `TokenManager.sendToken` function.
2. Since `metadata` is an input parameter needs to be passed into the function he passes the following random `metadata` since he thinks it is of no real importance. 

    `0x0000000012345678`

(This is because he is calling the `sendTransfer` function and not the `callContractWithInterchainToken` which is used to pass data). So he thinks `the data` passed in is of no real use and will be ignored by the protocol.

3. The `TokenManager.sendToken` function calls the `interchainTokenService.transmitSendToken`. since the `metadata.length > 0` it will `decode` the metadata.  

4. Since the first `4` bytes of the above passed in metadata results in `0` the transaction will proceed to execute.

5. It will construct the payload with the `metadata = 0x12345678` and will be passed into the `interchainTokenService._callContract`.

6. When the `_callContract` function calls the destination `interchainTokenService` and decodes the payload and later tries to call the function in the `destinationAddress` with the above passed in `metadata` the transaction will `revert` since there is no function related to the above invalid metadata.

7. As a result the user will lose his `gasValue` passed in as the `msg.value` to the `TokenManager.sendToken` function call. This is due to gas is already consumed for the cross chain transfer in the `gasService.payNativeG
`setFlowLimit` EXECUTION COULD REVERT THE PENDING TRANSFER TRANSACTIONS
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact

The `InterchainTokenService.setFlowLimit` function, is used to set the `flow limit` of the token managers of the current chain.

But there is no `timelock` in this function. Hence if the `operator` calls this function with high gas amount, this transaction will execute before other pending token transfer `transactions`. Hence transfer transaction currently in the `mempool` could revert once received at the respective `tokenManger` due to `flow limit exceed` if the flow limit had been decreased due to the `setFlowLimit` function execution.

This could lead to loss of funds to the transfer sender since he will lose on the native token spent as the `gasValue`. And this will lead to bad user experience since multiple transactions getting reverted.

## Proof of Concept

```solidity
    function setFlowLimit(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external onlyOperator {
        uint256 length = tokenIds.length;
        if (length != flowLimits.length) revert LengthMismatch();
        for (uint256 i; i < length; ++i) {
            ITokenManager tokenManager = ITokenManager(getValidTokenManagerAddress(tokenIds[i]));
            tokenManager.setFlowLimit(flowLimits[i]);
        }
    }
```

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

## Tools Used
Manual Review and VSCode

## Recommended Mitigation Steps

Hence it is recommended to add a `timelock` to the execution of the `InterchainTokenService.setFlowLimit` so the users are informed of the flow limit changes happening in the token managers of the respective chain. so they can adapt their transfer amounts to align with the current `flow limits` of the respective `token managers`.


## Assessed type

Other
[M] sendProposals reverts due to exceeding gas limit
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/interchain-governance-executor/InterchainProposalSender.sol#L59


# Vulnerability details

## Impact
In InterchainProposalSender, function sendProposals reverts due to exceeding gas limit.

The bug arises from unpredictable gas estimation during transaction execution, leading to transaction reverts. The block gas limit is 30000000, but the contract's gas estimation failed to accurately predict the required gas for the call to sendProposals, causing the transaction to fail, creating a DOS state.

## Proof of Concept
```
describe('sendProposals', function () {
        it.only('should return eth if it reverts on sendProposals', async function () {
            const target = await ethers.getSigners().then((signers) => signers[1].getAddress());
            const valueToSend = ethers.utils.parseEther('2');
            await signer.sendTransaction({
                to: sender.address,
                value: valueToSend,
            });
            const calls = [
                {
                    target,
                    value: 0,
                    callData: ethers.utils.randomBytes(32),
                },
                {
                    target,
                    value: 1,
                    callData: ethers.utils.randomBytes(32),
                },
                {
                    target,
                    value: 2,
                    callData: ethers.utils.randomBytes(32),
                },
            ];

            const destChains = ['avalanche', 'binance'];

            const xCalls = [
                {
                    destinationChain: destChains[0],
                    destinationContract: ethers.constants.AddressZero,
                    gas: 1,
                    calls,
                },
                {
                    destinationChain: destChains[1],
                    destinationContract: ethers.constants.AddressZero,
                    gas: 1,
                    calls,
                },
            ];

            const payload = ethers.utils.defaultAbiCoder.encode(
                ['address', 'tuple(address target, uint256 value, bytes callData)[]'],
                [signerAddress, calls],
            );

            const initialSenderBalance = await hre.ethers.provider.getBalance(sender.address);
            console.log('Initial Sender Balance:', initialSenderBalance.toString());

                // block gas limit 30000000
            for (const destChain of destChains) {
                const tx = await sender.sendProposals(xCalls, { value: 2, gasLimit: 30000000});
                const receipt = await tx.wait();
                console.log('Initial Sender Balance:', initialSenderBalance.toString());

                if (receipt.status === 0) {
                    // Transaction reverted, so the sender should receive the refunded ETH
                    const finalSenderBalan
Zero address check is required for _setOperator() and _setDistributor()
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/utils/Distributable.sol#L39-L44
https://github.com/code-423n4/2023-07-axelar/blob/2f9b234bb8222d5fbe934beafede56bfb4522641/contracts/its/utils/Operatable.sol#L39-L44


# Vulnerability details

## Impact
Currently, operator and distributor can be set as zero address due to missing zero address check, so once zero address is set, onlyOperator(or onlyDistributor) actions will never be performed.

As external setOperator(setDistributor) function call is restricted by current operator(distributor), it can't be further updated once it is set as zero address.

The only way to change operator(distributor) will be redeploy relevant contract by using proxy.

## Proof of Concept

```javascript
        it('Distributor can be set as zero address', async () => {
            const newAddress = '0x0000000000000000000000000000000000000000';
            await expect(token.setDistributor(newAddress)).to.emit(token, 'DistributorChanged').withArgs(newAddress);
            await expect(await token.distributor()).to.equal('0x0000000000000000000000000000000000000000');
            await expect(token.setDistributor(wallet.address)).to.be.revertedWithCustomError(service, 'NotDistributor');
        });
```

```javascript
        it('Operator can be set as zero', async() => {
            // Service was already deployed with zero address operator
            await expect(await service.operator()).to.equal('0x0000000000000000000000000000000000000000');
            await expect(service.setOperator(wallet.address)).to.be.revertedWithCustomError(service, 'NotOperator');
        });
```

## Tools Used
Manual Review

## Recommended Mitigation Steps

Add zero address check at the beginning of internal `_setOperator()` and `_setDistributor()` functions like ownership. 





## Assessed type

Access Control
Wrong comandID number can cause loss of funds for executor of expressReceiveToken() and expressReceiveTokenWithData()
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

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


# Vulnerability details

## Impact

During the execution of express receive functions in the `InterchainTokenService` contract, the express caller transfers funds to the destination address. However, a vulnerability exists in the `expressReceiveToken` function where the if statement checking whether the `commandId` has already been executed may return false if the `commandId` does not exist. This flaw allows an attacker to bypass this protection mechanism.

## Proof of Concept

    function expressReceiveToken(
        bytes32 tokenId,
        address destinationAddress,
        uint256 amount,
        bytes32 commandId
    ) external {
        if (gateway.isCommandExecuted(commandId)) revert AlreadyExecuted(commandId); //@Mid check if doesn't exist

        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);
    }

    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);
    }


The `isCommandExecuted` function returns a bool value after checking the `_boolStorage mapping (mapping(bytes32 => bool) private _boolStorage;)`.

    function isCommandExecuted(bytes32 commandId) public view override returns (bool) {
        return getBool(_getIsCommandExecutedKey(commandId));
    }

If the `commandId` does not exist, the `getBool` function will return false, which allows the attacker to bypass the if statement in the `expressReceiveToken()` function. Consequently, the attacker can send tokens to the destination address without the actual execution required by the corresponding commandId.

Moreover, this function does not perform a complex hash verification of `tokenId`, `destination address`, `amount`, and `commandId`, making the express receive functi
Replace .transfer() with .call() to Avoid Potential Failures Due to Gas Limitations
Audit: 2023-07-axelar-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/test/AxelarGasService.sol#L225
https://github.com/code-423n4/2023-07-axelar/blob/main/contracts/its/test/AxelarGasService.sol#L240


# Vulnerability details

Even though the contract is not explicitly in scope it's being inherited and is crucial to one that is in scope `InterchainProposalSender.sol`

## Impact
 There are a number of issues with using .transfer(), as it can fail for a number of reasons (specified in the Proof of Concept).


## Proof of Concept

1- The destination is a smart contract that doesn’t implement a payable function or it implements a payable function but that function uses more than 2300 gas units.

2- The destination is a smart contract that doesn’t implement a payable fallback function or it implements a payable fallback function but that function uses more than 2300 gas units.

3- The destination is a smart contract but that smart contract is called via an intermediate proxy contract increasing the case requirements to more than 2300 gas units. A further example of unknown destination complexity is that of a multisig wallet that as part of its operation uses more than 2300 gas units.

4- Future changes or forks in Ethereum result in higher gas fees than transfer provides. The .transfer() creates a hard dependency on 2300 gas units being appropriate now and into the future.


## Tools Used
Manual review

## Recommended Mitigation Steps
Instead use the .call() function to transfer Ether and avoid some of the limitations of .transfer().



## Assessed type

ERC20