xanoutas/solidity-security-findings huggingface dataset:
sendToken() function inside ERC721Vault is completely broken
Audit: 2024-03-taiko-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L35


# Vulnerability details

## Details & Impact
No user can send any ERC721 token due to use of `!=` instead of `==` on [L35](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L35):
```js
  File: contracts/tokenvault/ERC721Vault.sol

  21:               /// @notice Transfers ERC721 tokens to this vault and sends a message to the
  22:               /// destination chain so the user can receive the same (bridged) tokens
  23:               /// by invoking the message call.
  24:               /// @param _op Option for sending the ERC721 token.
  25:               /// @return message_ The constructed message.
  26:               function sendToken(BridgeTransferOp memory _op)
  27:                   external
  28:                   payable
  29:                   nonReentrant
  30:                   whenNotPaused
  31:                   withValidOperation(_op)
  32:                   returns (IBridge.Message memory message_)
  33:               {
  34:                   for (uint256 i; i < _op.tokenIds.length; ++i) {
  35:  @--->                if (_op.amounts[i] != 0) revert VAULT_INVALID_AMOUNT();
  36:                   }
```

## Tools Used
Manual review

## Recommended Mitigation Steps
```diff
  File: contracts/tokenvault/ERC721Vault.sol

  21:               /// @notice Transfers ERC721 tokens to this vault and sends a message to the
  22:               /// destination chain so the user can receive the same (bridged) tokens
  23:               /// by invoking the message call.
  24:               /// @param _op Option for sending the ERC721 token.
  25:               /// @return message_ The constructed message.
  26:               function sendToken(BridgeTransferOp memory _op)
  27:                   external
  28:                   payable
  29:                   nonReentrant
  30:                   whenNotPaused
  31:                   withValidOperation(_op)
  32:                   returns (IBridge.Message memory message_)
  33:               {
  34:                   for (uint256 i; i < _op.tokenIds.length; ++i) {
- 35:                       if (_op.amounts[i] != 0) revert VAULT_INVALID_AMOUNT();
+ 35:                       if (_op.amounts[i] == 0) revert VAULT_INVALID_AMOUNT();
  36:                   }
```



## Assessed type

Invalid Validation
Insecure Access Control in Timelock Contract Allowing Immediate Execution of Scheduled Transactions
Audit: 2024-03-taiko-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/script/AuthorizeTaikoForMultihop.s.sol#L15-L34


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
description: The Timelock Contract Implementation in the `run()` function of the provided script contains a critical security vulnerability due to insecure access control. The script schedules and immediately executes transactions on a set of contracts without enforcing the intended time-delay designed for security purposes. The root cause of this vulnerability is the lack of enforcement of a delay period between the scheduling (`timelock.schedule(...)`) and the execution (`timelock.execute(...)`) of the payload. This flaw permits unauthorized immediate execution of potentially sensitive operations, such as changing authorization states in the `SignalService` contract. The maximum achievable impact of this vulnerability could be the unauthorized modification of critical contract states, manipulation of governance mechanisms, misappropriation of funds, or other adverse actions that could compromise the integrity and security of the system. This vulnerability circumvents the security assumptions of the timelock mechanism, intended to provide a window for detecting and mitigating malicious activities.
## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/script/AuthorizeTaikoForMultihop.s.sol#L15-L34
## Tools Used

## Recommended Mitigation Steps
Finding Recommendation:

To address the vulnerability related to Insecure Access Control in the Timelock Contract Implementation, the following recommendations are suggested:

1. Implement Time Delay: Ensure that the `execute` function of the Timelock contract enforces the intended time delay before executing scheduled transactions. This delay should provide a security window during which any malicious actions can be detected and mitigated.

2. Role-Based Access Control: Implement role-based access controls within the Timelock contract to restrict the execution of scheduled transactions to authorized entities, such as governors or administrators. This will prevent unauthorized parties from executing arbitrary transactions.

3. Review Authorization Logic: Review the authorization logic in the `SignalService.authorize` function to ensure that only legitimate actions are authorized for the `taikoContracts`. This will help prevent unauthorized changes to contract states or governance functions.

4. Security Audit: Conduct a comprehensive security audit of the entire codebase, including the Timelock contract and related contracts, to identify and address any other potential vulnerabilities or security weaknesses.

By implementing these recommendations, the vulnerability related to Insecure Access Control in the Timelock
Potential Message Processing Blockage in LayerZero Messaging System
Audit: 2024-03-taiko-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L115-L152


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
description: The provided code sample contains a vulnerability related to the processing of cross-chain messages in a LayerZero-based application. The vulnerability arises from the handling of messages that fail to process and are marked as `RETRIABLE`. An attacker could exploit this by sending a message that is intentionally designed to fail upon processing, causing the message to enter a `RETRIABLE` state indefinitely. This could lead to a denial-of-service (DoS) condition by blocking the message queue and preventing other legitimate messages from being processed. Additionally, the vulnerability could be used to trigger unnecessary signals and potentially cause griefing, or to manipulate the recallMessage function to freeze funds associated with the message. The maximum achievable impact of this vulnerability includes the temporary freezing of funds, disruption of the normal operation of the contract, and a failure to deliver promised returns, severely affecting the integrity and availability of the LayerZero message relay system.
## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L115-L152
## Tools Used

## Recommended Mitigation Steps
Finding: The code contains a vulnerability related to the insecure message handling process, particularly around messages marked as `RETRIABLE` that fail to resolve, potentially leading to a blockage in the message queue.

Recommendation: To address this vulnerability, it is recommended to implement a mechanism that handles messages marked as `RETRIABLE` in a more robust manner. This could include setting a limit on the number of retries allowed for processing such messages, implementing a timeout mechanism to prevent indefinite blockage, or adding additional checks to ensure that messages are eventually processed or marked as failed after a certain number of retries. Additionally, thorough testing and auditing of the message handling logic should be conducted to identify and address any potential vulnerabilities in the code.


## Assessed type

DoS
Unauthorized Withdrawal Vulnerability in Smart Contract
Audit: 2024-03-taiko-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L88-L94


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
description: The 'withdraw' function in the provided Solidity code is vulnerable due to insufficient authorization checks, allowing any external caller to withdraw ERC20 tokens on behalf of any user address specified. The function does not verify whether the 'msg.sender' is indeed the 'user' intended to withdraw funds, potentially enabling an attacker to withdraw other users' tokens from the 'vault'. This vulnerability can lead to unauthorized fund transfers and direct theft of user assets if exploited.
## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L88-L94
## Tools Used

## Recommended Mitigation Steps
Finding Recommendation:
To address the vulnerability of improper authorization in the `withdraw` function, it is recommended to implement access control checks to ensure that only the `user` address can initiate withdrawals for their own funds. This can be achieved by verifying that `msg.sender` is equal to `user` before allowing the withdrawal to proceed. Additionally, consider implementing role-based access control or permission levels to restrict who can call the `withdraw` function. By implementing these authorization checks, you can prevent unauthorized withdrawals and protect user funds from being accessed by malicious actors.


## Assessed type

Access Control
Failure to Refund Excess ETH Payments in Smart Contract Function
Audit: 2024-03-taiko-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L77-L107


# Vulnerability details

## Impact
Detailed description of the impact of this finding.
description: The smart contract fails to refund excess payments due to the lack of a mechanism to handle the overpaid ETH. Users sending more ETH than needed for the transaction will not receive a refund, resulting in a potential loss of funds as the entire `msg.value` is forwarded to the recipient address without validation of the necessary amount or a refund process.
## Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L77-L107
## Tools Used

## Recommended Mitigation Steps
Finding Recommendation:
To address the vulnerability related to the failure to refund excess payments in the smart contract, it is recommended to implement a mechanism that checks if the `msg.value` sent by the user is excessive. If the `msg.value` exceeds the required amount for the transaction, the contract should refund the excess ETH back to the sender.

Here are the steps to implement the finding recommendation:
1. Add a check in the `onMessageInvocation` function to compare the `msg.value` with the expected amount for the transaction.
2. If the `msg.value` is greater than the required amount, implement a refund mechanism using the `transfer` or `send` function to send the excess ETH back to the sender's address.
3. Emit an event or log message to notify the user about the refund transaction.
4. Update the contract documentation and user interface to inform users about the refund policy in case of excess payments.

By implementing the above recommendations, the smart contract will provide better security and transparency to users, ensuring that excess payments are promptly refunded, thus preventing potential loss of user funds.


## Assessed type

ETH-Transfer
Backdoor in withdraw function in TaikoL2
Audit: 2024-03-taiko-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/TaikoL2.sol#L163-L178
https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/TaikoL2.sol#L176


# Vulnerability details

## Impact

The `TaikoL2.withdraw` has wrong logic that allows the owners or named withdrawer to steal all deposited tokens, or a rug-pull.


## Proof of Concept

[withdraw](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/TaikoL2.sol#L163-L178)
```solidity
    function withdraw(
        address _token,
        address _to
    )
        external
        onlyFromOwnerOrNamed("withdrawer")
        nonReentrant
        whenNotPaused
    {
        if (_to == address(0)) revert L2_INVALID_PARAM();
        if (_token == address(0)) {
            _to.sendEther(address(this).balance);
        } else {
            IERC20(_token).safeTransfer(_to, IERC20(_token).balanceOf(address(this)));
        }
    }
```



## Tools Used

in-house tool

## Recommended Mitigation Steps

- Limit Withdrawal Amounts: Add checks within the withdraw function to restrict the number of tokens withdrawn in a single transaction or a defined timeframe.

- Whitelisted tokens





## Assessed type

Rug-Pull
Contract initialization failure
Audit: 2024-03-taiko-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L111-L129
https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L95-L107


# Vulnerability details

## Impact
Function `__Essential_init` expects to parameters but only gets one within the function `init`. This will cause a revert and fail to initialize the contract.

## Proof of Concept
`init` is the function that calls the __Essential_init function  
    function init(
        address _owner,
        address _taikoToken,
        address _costToken,
        address _sharedVault
    )
        external
        initializer
    {
        __Essential_init(_owner);
        if (_taikoToken == address(0)) revert INVALID_PARAM();
        taikoToken = _taikoToken;

        if (_costToken == address(0)) revert INVALID_PARAM();
        costToken = _costToken;

        if (_sharedVault == address(0)) revert INVALID_PARAM();
        sharedVault = _sharedVault;
    }
The __Essential_init function

    function __Essential_init(
        address _owner,
        address _addressManager
    )
        internal
        virtual
        onlyInitializing
    {
        __Essential_init(_owner);

        if (_addressManager == address(0)) revert ZERO_ADDR_MANAGER();
        __AddressResolver_init(_addressManager);
    }

## Recommended Mitigation Steps
Ensure that "address _owner" and "address _addressManager" are passed in ass parameters.  


## Assessed type

Invalid Validation
Malicious owner can set address to unsupported chains
Audit: 2024-03-taiko-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L38


# Vulnerability details

## Impact
AddressManager, allows for the management of addresses mapped against a combination of a chain ID and a name. This functionality is crucial for applications that operate across multiple blockchain networks, providing a dynamic and flexible way to manage addresses specific to each network.

## Proof of Concept
The function setAddress takes a _chainId, a _name, and a _newAddress, and updates the mapping with the new address if the new address is not the same as the old one. It emits an AddressSet event upon a successful update. The only check performed before updating the address is whether the new address is different from the old address associated with the given chain ID and name. There's no check to see if the chain ID is part of a list of supported chain IDs.

[Github:](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/AddressManager.sol#L38)

```
function setAddress(
        uint64 _chainId,
        bytes32 _name,
        address _newAddress
    )
        external
        virtual
        onlyOwner
    {
        address oldAddress = __addresses[_chainId][_name];
        if (_newAddress == oldAddress) revert AM_INVALID_PARAMS();
        __addresses[_chainId][_name] = _newAddress;
        emit AddressSet(_chainId, _name, _newAddress, oldAddress);
    }
    
```

## Tools Used
Manual

## Recommended Mitigation Steps
Validate the chain ID against a list of supported chain IDs. This can help prevent errors or malicious attempts to set addresses for unsupported or incorrect chain IDs.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "./IAddressManager.sol";
import "./EssentialContract.sol";

contract AddressManager is EssentialContract, IAddressManager {
    mapping(uint256 => mapping(bytes32 => address)) private __addresses;
    mapping(uint256 => bool) private supportedChainIds;

    uint256[49] private __gap;

    event AddressSet(uint64 indexed chainId, bytes32 indexed name, address newAddress, address oldAddress);

    error AM_INVALID_PARAMS();
    error AM_UNSUPPORTED();
    error AM_CHAIN_ID_NOT_SUPPORTED();

    function init(address _owner) external initializer {
        __Essential_init(_owner);
    }

    function setAddress(uint64 _chainId, bytes32 _name, address _newAddress) external onlyOwner {
        if (!supportedChainIds[_chainId]) revert AM_CHAIN_ID_NOT_SUPPORTED();
        address oldAddress = __addresses[_chainId][_name];
        if (_newAddress == oldAddress) revert AM_INVALID_PARAMS();
        __addresses[_chainId][_name] = _newAddress;
        emit AddressSet(_chainId, _name, _newAddress, oldAddress);
    }

    function getAddress(uint64 _chainId, bytes32 _name) public view override returns (address) {
        return __addresses[_chainId][_name];
    }

    fu
Stuck Tokens after claim and withdraw period
Audit: 2024-03-taiko-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L39
https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L88


# Vulnerability details

## Impact
There is no functionality for withdrawing tokens not claimed or withdrawn and can cause funds to be permanently stuck in the airdrop contract

## Proof of Concept
There is no function that allows an admin or permitted EOA to withdraw tokens left after claim and withdrawal period as seen in 

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L88

## Tools Used

Manual Review

## Recommended Mitigation Steps

Add a new function with admin access control to clear the rest of the token but should only be allowed to be called if no ongoing withdrawals.

Something similar to
```solidity
// function to clear remaining tokens
function transferTokenBalance(address recipient) public onlyAdmin {
         if (!(claimEnd > block.timestamp || claimEnd + withdrawalWindow < block.timestamp)) {
            revert WITHDRAWALS_STILL_ONGOING();
        }
        uint256 balance = IERC20(token).balanceOf(address(this)); // Get contract's token balance
        require(balance > 0, "Contract has no token balance");

        require(IERC20(token).transfer(recipient, balance), "Transfer failed"); // Transfer tokens to recipient
    }

```


## Assessed type

ERC20
Gas Limit can be Exceeded in `verifyBlocks` Due to Static Block Verification Cap
Audit: 2024-03-taiko-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L85


# Vulnerability details

## Impact
The `verifyBlocks` function within the Taiko protocol is designed to process a predefined maximum number of blocks (`_maxBlocksToVerify`) per invocation. This approach does not take into account the fluctuating nature of Ethereum gas costs and the block gas limit, potentially leading to transaction failures when the operation's gas cost exceeds the block gas limit. This static limit does not adjust for the complexity of verifying each block, which can vary significantly, thereby risking transaction failure and impacting the protocol's ability to timely verify blocks.


## Proof of Concept
1. **Initial Setup:** The protocol sets `_maxBlocksToVerify` to a high number to maximize throughput in block verifications per transaction.
2. **Variable Block Complexity:** Some blocks require complex computations or interactions with external contracts, significantly increasing gas usage.
3. **Transaction Failure:** When `verifyBlocks` is invoked with the maximum number of blocks set by `_maxBlocksToVerify`, the cumulative gas required exceeds the Ethereum block gas limit, causing the transaction to fail.
4. **Consequence:** Repeated failures to verify blocks due to gas limit issues can lead to backlog, impacting the protocol's efficiency and potentially its security model due to delayed block verifications.

## Tools Used
Manual

## Recommended Mitigation Steps

Introduce a dynamic check within the `verifyBlocks` function to assess the gas usage continuously and stop processing additional blocks if the remaining gas falls below a certain threshold. This can be achieved by estimating gas usage for each block verification and comparing it against the remaining gas.

```solidity
// Example modification in verifyBlocks function
uint64 initialGas = gasleft();
uint64 gasUsed = 0;
uint64 gasThreshold = 200000; // Set a gas threshold to ensure the transaction does not run out of gas

while (blockId < b.numBlocks && numBlocksVerified < _maxBlocksToVerify) {
    uint64 gasBeforeVerification = gasleft();
    
    // Existing block verification logic here...

    uint64 gasAfterVerification = gasleft();
    gasUsed += (gasBeforeVerification - gasAfterVerification);

    if (initialGas - gasUsed < gasThreshold) {
        break; // Stop verifying more blocks if we're close to the gas limit
    }
    
    // Continue with the next block...
}
```



## Assessed type

DoS