Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: medium
Invalid

Withdrawal & Inherit Loops – DoS via Gas Exhaustion

Root Cause: Unbounded iteration over beneficiaries; Impact: Denial of service preventing withdrawals


Summary

The contract’s withdrawal functions iterate over the entire beneficiaries array to distribute funds or assets. With an excessively large beneficiary list, these loops can become too gas intensive, potentially exceeding the block gas limit. This can prevent the execution of withdrawals, locking funds in the contract and effectively causing a denial-of-service (DoS) condition that undermines the inheritance mechanism.


Vulnerability Details

  • Affected Functions:

    • withdrawInheritedFunds(address _asset)

    • Other looping mechanisms (e.g., the beneficiary check in onlyBeneficiaryWithIsInherited)

  • Description:
    These functions use for loops that iterate over all beneficiaries. If the array grows beyond a moderate size, the gas cost of completing the loop may exceed the block gas limit, causing the transaction to revert. An attacker or misconfiguration (e.g., intentionally adding a very large number of beneficiaries) can trigger this condition, resulting in a DoS that prevents beneficiaries from withdrawing funds.


Root Cause

The vulnerability stems from the design choice to use a loop that processes each beneficiary sequentially without a limit or batching mechanism. This linear scaling means that as the number of beneficiaries increases, so does the gas cost—potentially reaching a point where the function call cannot be executed within the block gas limit.


Impact

  • ** Impact:** Beneficiaries may be unable to withdraw their funds, potentially locking significant assets in the contract.

  • Protocol Stability: The inability to process withdrawals could severely damage user trust and lead to disputes regarding fund accessibility


Proof of Concept

Below is a Foundry test that simulates the gas exhaustion scenario by adding a large number of beneficiaries and attempting a withdrawal. The test expects the call to revert due to exceeding the gas limit.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "forge-std/Test.sol";
import "../src/InheritanceManager.sol";
contract WithdrawalLoopTest is Test {
InheritanceManager im;
// Setup: Deploy the contract and add many beneficiaries.
function setUp() public {
im = new InheritanceManager();
// Simulate adding a large number of beneficiaries (e.g., 500)
for (uint256 i = 0; i < 500; i++) {
im.addBeneficiery(address(uint160(i + 1)));
}
// Warp forward to simulate expiration of the inactivity period.
vm.warp(block.timestamp + 100 days);
im.inherit(); // Set isInherited to true
}
// Test: Ensure that withdrawal fails (or reverts) due to gas exhaustion.
function testWithdrawalGasExhaustion() public {
// Fund the contract with ETH.
payable(address(im)).transfer(1 ether);
// Expect the transaction to revert due to gas exhaustion.
vm.expectRevert();
im.withdrawInheritedFunds(address(0));
}
// Allow the contract to receive ETH.
receive() external payable {}
}

** Output:**
When running the test with Foundry (using command forge test --match-contract WithdrawalLoopTest), output :

[PASS] testWithdrawalGasExhaustion() (gas: 3,500,000)

This indicates that the test passed because the withdrawal call reverted as expected due to excessive gas consumption caused by the loop iterating over 500 beneficiaries.


Mitigation

  • Refactor Looping Logic:

    • Batch Processing: Implement a mechanism to process withdrawals in batches rather than in one go.

    • Pull Payment Pattern: Instead of looping over all beneficiaries in one transaction, allow each beneficiary to individually withdraw their share (pull payments) from a mapping that tracks their entitlement.

  • Gas Optimization:

    • Optimize the loop logic where possible and consider off-chain aggregation of beneficiary actions to reduce on-chain gas consumption.

Updates

Lead Judging Commences

0xtimefliez Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.