RustFund is a decentralized crowdfunding protocol. The README states that creators can withdraw funds only once their campaign succeeds (deadline reached AND goal met). However, the withdraw() function performs no such check. A creator can drain the fund at any moment, regardless of whether the campaign deadline has passed or the goal has been reached. Contributors who deposited SOL in good faith have no protection.
The root cause is the absence of any success-condition validation in lines 90-105. The function transfers the full amount_raised after only verifying that msg.sender is the fund creator (has_one = creator). No timestamp comparison against fund.deadline and no amount comparison against fund.goal is performed.
Likelihood: Always. As soon as any contributor deposits SOL, amount_raised becomes positive and withdraw becomes profitable for the creator. No external condition, rare state, or multi-step chain is required.
Impact: Direct theft of all contributed funds. Every contributor who deposits SOL can have their entire payment taken by the creator before the campaign concludes, regardless of outcome.
The test deploys RustFund on a local Solana validator, creates a campaign with a 1 SOL goal, contributes only 0.5 SOL (goal not met, deadline not set), then calls withdraw. The creator balance increases by the full 0.5 SOL deposited amount, proving no success condition exists.
On-chain evidence (Solana localnet):
Creator balance: 9,962,404,040 -> 10,462,399,040 lamports (+0.5 SOL)
Fund was never required to reach its 1 SOL goal
No deadline was ever set
Add three require statements at the top of withdraw():
Note that a new DeadlineNotSet error variant must be added to the ErrorCode enum. This three-part guard enforces the campaign lifecycle on-chain: create -> contribute -> deadline pass -> goal check -> withdraw, matching the documented behavior.
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.