RustFund

First Flight #36
Beginner FriendlyRust
100 EXP
View results
Submission Details
Severity: high
Valid

Missing goal verification in withdraw function allows withdrawal from unsuccessful campaigns

Description

The rustfund::withdraw function does not verify if the funding goal has been met before allowing the creator to withdraw all contributed funds. This contradicts the documented behavior in the README, which states: "Creators can withdraw funds once their campaign succeeds." According to the README, success is defined as meeting the funding goal.

Proof of Concept

  1. Creator creates a fund with a goal of 100 SOL and sets a deadline

  2. Contributors collectively contribute only 50 SOL, not meeting the goal

  3. The deadline passes (assuming this check is added to the withdraw function)

  4. Despite not meeting the goal, the creator can still call rustfund::withdraw to withdraw all contributed funds

  5. This violates the core principle of the crowdfunding platform where campaigns should only succeed if they meet their funding goals

// Current implementation (assuming deadline check is added) still lacks goal verification
pub fn withdraw(ctx: Context<FundWithdraw>) -> Result<()> {
// Assuming deadline check has been added here
// No check for whether goal was met
let amount = ctx.accounts.fund.amount_raised;
**ctx.accounts.fund.to_account_info().try_borrow_mut_lamports()? =
ctx.accounts.fund.to_account_info().lamports()
.checked_sub(amount)
.ok_or(ProgramError::InsufficientFunds)?;
**ctx.accounts.creator.to_account_info().try_borrow_mut_lamports()? =
ctx.accounts.creator.to_account_info().lamports()
.checked_add(amount)
.ok_or(ErrorCode::CalculationOverflow)?;
Ok(())
}

Recommendation

Approach 1: Add goal verification to the withdraw function

pub fn withdraw(ctx: Context<FundWithdraw>) -> Result<()> {
let fund = &ctx.accounts.fund;
// Assuming deadline check has been added here
+ // Only allow withdrawals if goal was met
+ if fund.amount_raised < fund.goal {
+ return Err(ErrorCode::GoalNotReached.into());
+ }
let amount = fund.amount_raised;
// Rest of the function...
}

This approach adds a proper state machine to track the campaign's status and enforces the correct withdrawal rules based on both deadline and goal achievement.

Updates

Appeal created

bube Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

No goal achievement check in `withdraw` function

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.