Normal behavior: When users have accumulated proceeds from orders, they should be able to withdraw them securely. The balance should be zeroed before any external calls to prevent withdrawal logic from being re-entered.
Issue: The contract makes an external ERC20 call first, then zeroes the user balance. This sequence breaks Solidity’s checks-effects-interactions paradigm. A malicious ERC777 or ERC20 fallback can re-enter the withdrawProceeds
function during the transfer, exploiting the unchanged balance to drain funds.
Likelihood:
This vulnerability occurs whenever a user holds proceeds and withdraws them using a token that supports callbacks (ERC777 or a malicious ERC20).
The prevalence of ERC777 or custom fallback tokens makes this a practical attack vector.
Impact:
Attackers can drain the contract’s reserves by repeatedly withdrawing before their balance is zeroed, bypassing intended economic constraints.
Results in complete depletion of funds reserved for other legitimate users.
Here, an attacker deploys a custom ERC777 with a tokensReceived
hook that calls withdrawProceeds()
again. Since the user balance isn't yet cleared, this second call succeeds, allowing the attacker to double (or infinitely) withdraw. Each re-entrant call reduces the contract’s pool meant for honest users.
Zeroing the balance before making the external call ensures that any re-entrant attempt sees a cleared balance, stopping repeated withdrawals. This pattern—known as checks-effects-interactions—is a critical Solidity security practice endorsed by the Ethereum community and OpenZeppelin contracts.
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.