The InheritanceManager smart contract includes three notable areas of concern: the contractInteractions function, which allows risky external calls, and two edge cases in removeBeneficiary and the onlyBeneficiaryWithIsInherited modifier. The external call functionality is flexible but dangerous due to its lack of input validation, potentially allowing the owner to lose funds to malicious contracts. The removeBeneficiary function creates gaps in the beneficiaries array, which can lead to funds being sent to the zero address or miscalculated distributions. The onlyBeneficiaryWithIsInherited modifier has an out-of-bounds loop issue that could cause unnecessary reverts. These issues could disrupt the contract’s core purpose of securely managing inheritance, but they can be audited and mitigated with careful testing and code adjustments.
1. External Calls in contractInteractions
Code:
solidity
Description: This function lets the owner call any external contract with arbitrary data (_payload) and ETH (_value). It’s protected by nonReentrant (using transient storage) and onlyOwner, but there’s no validation of _target or _payload.
Issue:
Arbitrary call{} usage means the owner could accidentally or intentionally interact with a malicious contract.
The documentation warns users to validate inputs, but the contract itself doesn’t enforce safety.
The ETH balance isn’t checked before sending _value, risking a revert if insufficient.
2. Array Gaps in removeBeneficiary
Code:
solidity
Description: Removes a beneficiary by setting their array slot to 0x0 using delete, but doesn’t resize the beneficiaries array.
Issue:
Leaves gaps (e.g., [addr1, addr2, addr3] becomes [addr1, 0x0, addr3] after removing addr2).
Loops in other functions (e.g., withdrawInheritedFunds) treat 0x0 as a valid recipient, potentially sending funds to it.
3. Out-of-Bounds Loop in onlyBeneficiaryWithIsInherited
Code:
solidity
Description: Restricts functions to beneficiaries after inheritance, looping through beneficiaries to verify msg.sender.
Issue:
The condition i < beneficiaries.length + 1 goes one step beyond the array’s valid indices (e.g., for length = 2, it checks index 2, which doesn’t exist).
Causes an out-of-bounds revert for non-beneficiaries instead of a clean failure.
External Calls (contractInteractions)
Worst Case: A malicious contract drains all ETH or tokens from InheritanceManager via a crafted callback or self-destruct exploit, despite the reentrancy guard.
Practical Impact: Beginners might misuse this function (e.g., wrong _payload), locking funds in another contract or triggering a revert, undermining the inheritance system’s reliability.
Array Gaps (removeBeneficiary)
Worst Case: Funds (ETH or ERC20) are sent to 0x0 and lost forever during withdrawInheritedFunds.
Practical Impact: Unequal distribution—e.g., 9 ETH split among [addr1, 0x0, addr3] gives 3 ETH each, losing 3 ETH to 0x0, instead of 4.5 ETH to addr1 and addr3. This breaks the “equally divided” assumption.
Modifier Loop (onlyBeneficiaryWithIsInherited)
Worst Case: No severe fund loss, but the contract becomes unusable for valid beneficiaries if the array access bug triggers unexpected reverts.
Practical Impact: Non-beneficiaries correctly can’t proceed, but the out-of-bounds error is sloppy and could confuse users or tools expecting a clear revert message.
Grok AI
Foundry
Add Validation:
Implement a whitelist of trusted _target addresses:
solidity
Balance Check: Add require(address(this).balance >= _value, "Insufficient ETH"); before the call.
Educate Users: Provide examples of safe _payload construction (e.g., for Aave deposits).
For removeBeneficiary
Resize Array: Use swap-and-pop to eliminate gaps:
solidity
Test: Verify withdrawInheritedFunds splits funds only among valid addresses after removal.
For onlyBeneficiaryWithIsInherited
Fix Loop: Rewrite for safety and clarity:
solidity
Benefit: Avoids out-of-bounds access, provides clear error messages, and is easier to debug.
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.