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

Unauthorized users can execute inheritance functions, leading to fund mismanagement.

Description: The InheritanceManager contract does not verify that msg.sender is a beneficiary before executing critical inheritance functions. This allows any external user to execute these functions, potentially manipulating the inheritance process and disrupting fund distribution.

The affected functions are:

  • inherit()

  • withdrawInheritedFunds()

  • buyOutEstateNFT()

Impact:

  • inherit() → This function has already been reported as vulnerable to an attack where an attacker can take control of the contract. However, in this case, the lack of beneficiary verification allows any user to activate inheritance without having any connection to the owner or legitimate beneficiaries. This breaks trust in the protocol, as inheritance can be triggered arbitrarily by unauthorized users.

  • withdrawInheritedFunds() → Any user can force the distribution of funds, even though the check for whether inheritance is active prevents immediate loss. However, in a contract that may handle large amounts of funds, allowing unauthorized users to trigger withdrawals compromises the protocol’s financial security.

  • buyOutEstateNFT() → Any user can call this function without being a beneficiary and without inheritance being active. While the NFT is burned after the transaction and has no value within the protocol, this allows unexpected actions in a contract of this scale, which could create distrust among users and facilitate system manipulation.

Proof of Concept: This test demonstrates a security flaw where any user, regardless of whether they are a beneficiary, can activate the inheritance phase by calling the inherit() function.

function test_unverifiedBeneficiary() public {
// Define addresses for testing
address emergencyWallet = makeAddr("emergencyWallet");
address alice = makeAddr("alice");
address bob = makeAddr("bob");
address charlie = makeAddr("charlie");
// Simulate the owner performing beneficiary assignments
vm.startPrank(owner);
// The owner adds multiple beneficiaries sequentially
im.addBeneficiery(emergencyWallet);
im.addBeneficiery(alice);
im.addBeneficiery(bob);
im.addBeneficiery(charlie);
// Stop acting as the owner
vm.stopPrank();
// Simulate inactivity for 90 days, reaching the inheritance trigger period
vm.warp(block.timestamp + 90 days);
// Define an unauthorized user (not a beneficiary)
address anyUser = makeAddr("anyUser");
// Unauthorized user attempts to trigger the inheritance process
vm.prank(anyUser);
im.inherit();
// Assert that the inheritance phase has been activated despite an unauthorized call
assertTrue(im.getIsInherited());
}

Tools Used

  • Manual review

  • Foundry for testing

Recommended Mitigation: We recommend adding the modifier InheritanceManager::onlyBeneficiaryWithIsInherited to each affected function to ensure that only legitimate beneficiaries can execute them.

Additionally, in the withdrawInheritedFunds() function, the existing isInherited check should be removed, as this verification is already handled by the modifier, preventing redundant checks and optimizing gas usage.

+ function withdrawInheritedFunds(address _asset) external onlyBeneficiaryWithIsInherited {
- function withdrawInheritedFunds(address _asset) external {
- if (!isInherited) {
- revert NotYetInherited();
- }
uint256 divisor = beneficiaries.length;
if (_asset == address(0)) {
uint256 ethAmountAvailable = address(this).balance;
uint256 amountPerBeneficiary = ethAmountAvailable / divisor;
for (uint256 i = 0; i < divisor; i++) {
address payable beneficiary = payable(beneficiaries[i]);
(bool success,) = beneficiary.call{value: amountPerBeneficiary}("");
require(success, "something went wrong");
}
} else {
uint256 assetAmountAvailable = IERC20(_asset).balanceOf(address(this));
uint256 amountPerBeneficiary = assetAmountAvailable / divisor;
for (uint256 i = 0; i < divisor; i++) {
IERC20(_asset).safeTransfer(beneficiaries[i], amountPerBeneficiary);
}
}
}
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.