withdraw (programs/rustfund/src/lib.rs) reads fund.amount_raised and transfers it to creator unconditionally. There is no check that fund.amount_raised >= fund.goal and no check that fund.deadline has passed:
The README states "Creators can withdraw funds once their campaign succeeds". Neither success condition is enforced.
Impact: High — the creator can take every contributed lamport immediately after contributions arrive, regardless of goal or deadline. All contributors lose their funds; the all-or-nothing model the protocol promises does not exist. After the withdrawal the fund PDA holds only rent, so any later refund fails with InsufficientFunds — contributors have no recourse. Irreversible; affects every campaign.
Likelihood: High — a single ordinary withdraw call by the creator, no preconditions, no special timing.
Test from tests/poc.ts (raw @solana/web3.js, instructions built by hand, run against solana-test-validator --bpf-program <program_id> target/deploy/rustfund.so):
Output:
Require both success conditions before transferring, and reset the counter afterwards:
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.