In the InheritanceManager.sol contract the inherit() and withdrawInheritedFunds are only supposed to be called by beneficiaries but currently anyone can call them, even when they are not beneficiaries and start the inheritance process.
The InheritanceManager.sol has the beneficiary function inherit, which is used to change the state of the contract to inheritable which opens up access to any funds and assets. The beneficiary function withdrawInheritedFunds calculates how much each beneficiary will get and sends the funds/assets. Currently, both beneficiary functions do not have any checks to make sure they can only be called by beneficiaries.
The error InvalidBeneficiaries and modifier onlyBeneficiaryWithIsInherited exist but are not implemented within the above functions logic.
The
inherit()missing modifier to check only beneficiaries can call
The
withdrawInheritedFundsmissing modifieronlyBeneficiaryWithIsInherited
As the @dev information provides, these functions are only supposed to be callable by only beneficiaries. While, no one can steal the inheritance funds/assets via this method resulting in the impact being low, this still breaks the protocols functionality as the code logic is not working as supposed to.
The impact is low as anyone can change the contract state once the 90 days has passed to inheritable and initiate the inheritance transfers which is against the protocols functionality and no funds are at risk. Furthermore, there is no profit for the attacker
Manual Review
Foundry for Testing
I have included a test function that can be run using: `forge test --mt testAnyoneCanCallInherit -vvv`.
The function:
Deposits 10 ether as the owner
Adds 2 beneficiaries
Fast forwards past the 90 day deadline
Calls inherit as a random user to change the contract state to inheritable
Calls withdrawInheritedFunds as a random user to initiate the inheritance transfers
Displays logs showing wallet balance before and after along with the beneficiaries balances
The recommended mitigation for this is
Implement a modifier that checks if the caller to inherit is part of the is part of the beneficiaries list before executing. An example of this is:
The modifier onlyBeneficiaryWithIsInherited exists but is not suitable for the inherit function as the modifier requires the current state to be isInherited = true. If its used, the contracts state will never be updated thus locking all funds forever and breaking contract logic.
The modifier onlyBeneficiaryWithIsInherited should be implemented on the withdrawInheritedFunds
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.