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

`withdrawInheritedFunds` function: The function lacks proper access control, allowing any address to trigger fund distribution

Summary

A high vulnerability has been identified in the InheritanceManager contract's withdrawInheritedFunds function. The function lacks proper access control, allowing any address to trigger fund distribution after the inheritance period, potentially leading to premature or unauthorized fund distribution.

Vulnerability Details

The vulnerability exists in the withdrawal mechanism:

  1. Missing Access Control:

  • The withdrawInheritedFunds function lacks a modifier to restrict calls to beneficiaries only

  • Any external address can trigger fund distribution

  • No consensus mechanism among beneficiaries for withdrawal timing

  1. Test Demonstration Shows:

  • Contract is set up with two beneficiaries (user1 and user2)

  • Contract is funded with 10e10 wei

  • After inheritance period (90 days):

    • An unauthorized address (badGuy) can call inherit()

    • Same unauthorized address can trigger fund distribution

    • Funds are distributed to beneficiaries without their consent

From the test:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {Test, console} from "forge-std/Test.sol";
import {InheritanceManager} from "../src/InheritanceManager.sol";
import {ERC20Mock} from "@openzeppelin/contracts/mocks/token/ERC20Mock.sol";
contract InheritanceManagerAuditTest is Test {
InheritanceManager im;
ERC20Mock usdc;
ERC20Mock weth;
address owner = makeAddr("owner");
address user1 = makeAddr("user1");
function setUp() public {
vm.prank(owner);
im = new InheritanceManager();
usdc = new ERC20Mock();
weth = new ERC20Mock();
}
// test anyone can call withdrawInheritedFunds, maybe it is not right time to withdraw funds, only beneficiaries should decide to withdraw funds
// fix: add modifier onlyBeneficiaries
function test_badGuyCallUnauthWithdrawFunds() public {
address badGuy = makeAddr("badGuy");
address user2 = makeAddr("user2");
vm.startPrank(owner);
im.addBeneficiery(user1);
im.addBeneficiery(user2);
vm.stopPrank();
assertEq(0, address(user1).balance);
assertEq(0, address(user2).balance);
uint256 amount = 10e10;
vm.deal(address(im), amount);
vm.warp(1 + 90 days);
vm.startPrank(badGuy);
im.inherit();
im.withdrawInheritedFunds(address(0));
vm.stopPrank();
assertEq(amount / 2, address(user1).balance);
assertEq(amount / 2, address(user2).balance);
}
}

The test proves this by:

  1. Setting up contract with two beneficiaries

  2. Funding the contract with 10e10 wei

  3. Waiting for inheritance period

  4. Showing that an unauthorized address can:

    • Call inherit()

    • Trigger fund distribution via withdrawInheritedFunds

  5. Demonstrating funds are distributed:

    • user1 receives 5e10 wei

    • user2 receives 5e10 wei

    • Distribution occurs without beneficiary consent

Impact

High severity. The vulnerability allows:

  • Unauthorized triggering of fund distribution

  • Premature distribution of inheritance

  • No beneficiary control over withdrawal timing

  • Potential disruption of intended inheritance plans

Tools Used

  • Manual code review

  • Foundry test framework

  • Custom test cases demonstrating unauthorized withdrawal

  • Access control analysis

Recommendations

  1. Implement proper access control:

contract InheritanceManager {
modifier onlyBeneficiary() {
bool isBeneficiary = false;
for(uint i = 0; i < beneficiaries.length; i++) {
if(msg.sender == beneficiaries[i]) {
isBeneficiary = true;
break;
}
}
require(isBeneficiary, "Caller is not a beneficiary");
_;
}
function withdrawInheritedFunds(address _tokenAddress) external onlyBeneficiary {
require(block.timestamp >= deadline, "Deadline not reached");
// Continue with existing distribution logic...
}
}
  1. Add withdrawal coordination mechanism:

  • Require multiple beneficiary signatures

  • Implement timelock for withdrawals

  • Add withdrawal voting system

  1. Enhance security measures:

  • Add events for withdrawal requests

  • Implement withdrawal delays

  • Add emergency pause functionality

Updates

Lead Judging Commences

0xtimefliez Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Appeal created

alekseyts Submitter
9 months ago
0xtimefliez Lead Judge
9 months ago
0xtimefliez Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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

Give us feedback!