The withdraw function in the smart contract fails to properly verify the ownership of a deposit, allowing a malicious actor to withdraw funds from another user’s deposit. This vulnerability arises from relying solely on EnumerableSet.contains(userDeposits[msg.sender], depositId), which can be manipulated in certain cases. By explicitly checking that the msg.sender is the original depositor recorded in depositInfo[depositId], the issue is mitigated.
• Affected Function: withdraw(address recipient, uint256 depositId)
• Root Cause: The contract relies on EnumerableSet to verify deposit ownership instead of checking the actual depositor stored in depositInfo.
• Exploit Scenario:
1. Alice deposits funds.
2. Bob manipulates the contract (e.g., if there’s an unintended way to modify userDeposits to include an unauthorized deposit ID).
3. Bob calls withdraw() with Alice’s deposit ID and extracts her funds.
• Before Fix (Vulnerable Code):
• Issue: This check only verifies if depositId exists in userDeposits[msg.sender], which could be modified or incorrectly updated in edge cases.
• After Fix (Safe Code):
• Solution: This explicitly verifies that the caller (msg.sender) is the actual original depositor, preventing unauthorized withdrawals.
• Unauthorized users can withdraw funds from other users, leading to potential loss of assets.
• This vulnerability could be exploited in edge cases where deposit mappings are incorrectly modified (e.g., smart contract upgrades, mismanaged ownership transfers).
• Foundry (forge-std/Test.sol) for smart contract testing
• Manual Code Review to identify ownership validation issues
• PoC Attack Contract to simulate unauthorized withdrawal
• Explicitly check deposit ownership: Always verify that msg.sender matches the depositor field in depositInfo[depositId].
• Use structured access control: Implement access control mechanisms such as onlyDepositor modifiers.
• Audit state-changing functions: Ensure no other contract functions can manipulate userDeposits in unintended ways.
• Test edge cases: Simulate different attack vectors, including unauthorized deposit modifications, re-assignments, and governance actions.
There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.
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.