amount_raised is monotonically increasing: refund() (an outflow) never decrements it and withdraw() never zeroes it. After contribute → withdraw → contribute → withdraw, the second withdraw() reverts with InsufficientFunds (checked_sub against the stale amount_raised), and the new contributions are permanently locked in the PDA (refunds pay 0 per H-1, withdraw() always reverts).
In programs/rustfund/src/lib.rs: refund() transfers lamports out of the fund vault but leaves fund.amount_raised untouched; withdraw() transfers the full amount_raised out but never sets it to 0. Any subsequent withdraw() computes against a stale, too-high amount_raised and reverts on the checked subtraction.
Medium severity / Medium likelihood: bricks the fund after one withdrawal cycle. New contributions after a withdrawal are permanently locked — not refundable (H-1 pays 0), not withdrawable (always reverts). Funds are lost with no recovery.
Verified via line-by-line manual review plus an off-chain Rust logic mirror of the handler flow (5/5 mirror PoCs passing; no Solana validator was available):
contribute(1 SOL) → withdraw() succeeds (1 SOL out).
contribute(0.5 SOL) → second withdraw() reverts InsufficientFunds; 0.5 SOL locked forever.
fund.amount_raised = fund.amount_raised.checked_sub(amount).unwrap(); in refund(); set fund.amount_raised = 0; in withdraw() after the transfer.
Access control on privileged fns (has_one = creator + Signer) and checked math on the transfers themselves were verified sound.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.