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

Improper Beneficiary Removal Leads to Permanent DoS

Summary

The InheritanceManager.sol::removeBeneficiary() function incorrectly removes a beneficiary by setting beneficiaries[index] to address(0) instead of properly adjusting the array. This results in an inconsistent beneficiaries.length, leading to permanent DoS in critical functions like withdrawInheritedFunds() and buyOutEstateNFT() when trying to transfer and allocate ERC20 tokens among beneficiaries. Both functions will always revert due to trying transfer tokens to the zero address.

Vulnerability Details

Affected code:

The main problem of the current implementation is that the delete keyword in Solidity does not reduce the array’s length - it only resets the specified index to address(0), leaving a “hole” in the array.

For example, if the owner set three beneficiaries and later removed one, although there are only 2 beneficiers the length will still be 3. Then, whenever withdrawInheritedFunds() or buyOutEstateNFT() are called to transfer ERC20 tokens, the functions will always revert because of trying to send tokens to the zero address and thus preventing other beneficiaries to receive their deserved share of the funds.

PoC

Add the following tests to the InheritanceManagerTest.t.sol contract.

The PoC demonstrates the DoS in the withdrawInheritedFunds() when transferring and allocating ERC20 tokens like USDC among beneficiaries.

function test_withdrawInheritedFundsWillRevertWhenTransferingERC20()
public
{
uint256 balance = 100000e6;
address imAddress = address(im);
address alice = address(0x01);
address bob = address(0x02);
address john = address(0x03);
vm.startPrank(owner);
// mint 100k USDC to owner
usdc.mint(owner, balance);
// owner sets 3 beneficiaries [Alice, Bob, John]
im.addBeneficiery(alice);
im.addBeneficiery(bob);
im.addBeneficiery(john);
// transfer USDC from owner to im
usdc.transfer(imAddress, balance);
// remove bob as he is the middle child...
// [Alice, 0x00, John]
im.removeBeneficiary(bob);
vm.stopPrank();
// 90 days pass, no activity
vm.warp(block.timestamp + 90 days + 1);
// inherit the funds of owner
im.inherit();
// withdraw funds and allocate among beneficiaries will revert for ERC20
vm.expectRevert();
im.withdrawInheritedFunds(address(usdc));
}
Ran 1 test for test/InheritanceManagerTest.t.sol:InheritanceManagerTest
[PASS] test_withdrawInheritedFundsWillRevertWhenTransferingERC20() (gas: 220800)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.77ms (1.11ms CPU time)

Impact

  • Permanent DoS of the withdrawInheritedFunds() and buyOutEstateNFT() when transferring ERC20 tokens.

It's important to mention that funds are not lost but a part of the core functionality of the protocol is broken that's why I believe that although the likelihood is medium, the impact is high (broken core functionality).

Tools Used

  • Manual review

  • Foundry

Recommendations

I would recommend is using the pop() method of the dynamic array in Solidity and swapping the last element with the removed one.

function removeBeneficiary(address _beneficiary) external onlyOwner {
uint256 indexToRemove = _getBeneficiaryIndex(_beneficiary);
//delete beneficiaries[indexToRemove];
beneficiaries[indexToRemove] = beneficiaries[beneficiaries.length - 1];
beneficiaries.pop();
}
Ran 1 test for test/InheritanceManagerTest.t.sol:InheritanceManagerTest
[FAIL: next call did not revert as expected] test_withdrawInheritedFundsWillRevertWhenTransferingERC20() (gas: 286451)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 4.44ms (3.50ms CPU time)
Ran 2 test suites in 9.72ms (5.66ms CPU time): 3 tests passed, 1 failed, 0 skipped (4 total tests)
Updates

Lead Judging Commences

0xtimefliez Lead Judge
3 months ago
0xtimefliez Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Incorrect removal from beneficiary list causes funds to be send to 0 address

0xtimefliez Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Incorrect removal from beneficiary list causes funds to be send to 0 address

Appeal created

0xalipede Submitter
3 months ago
0xtimefliez Lead Judge 3 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Incorrect removal from beneficiary list causes funds to be send to 0 address

Support

FAQs

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