RustFund

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

Goal Not Met Withdrawal Vulnerability

Summary

A critical vulnerability exists in the current implementation that allows fund withdrawals even when the fundraising goal has not been achieved, fundamentally breaking the core mechanism of crowdfunding.

Vulnerability Details

pub fn withdraw(ctx: Context<FundWithdraw>) -> Result<()> {
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(())
}

Impact

  • Allows creators to withdraw funds regardless of goal achievement

  • Breaks the docs **Refund Mechanism:** Contributors can get refunds if deadlines are reached and goals aren't met

  • Breaks contributor trust

  • Platform reputation damage

  • Contributors does not get refunded.

Proof Of concept

Scenario 1: Premature Fund Extraction

  • Creator launches campaign with $10,000 goal

  • Raises only $3,000

  • Withdraws entire $3,000

  • Contributors lose investments

Scenario 2: Repeated Incomplete Campaigns

  • Create multiple campaigns

  • Intentionally fail to meet goals

  • Continuously extract partial funds

  • Exploit platform's lack of validation

Recommendation

pub fn withdraw(ctx: Context<FundWithdraw>) -> Result<()> {
let fund = &ctx.accounts.fund;
let current_time = Clock::get()?.unix_timestamp;
// Strict Goal Achievement Validation
if fund.amount_raised < fund.goal {
return Err(ErrorCode::GoalNotMet.into());
}
let amount = fund.amount_raised;
// Existing transfer logic with added validation
**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(())
}
// Enhanced Error Codes
#[error_code]
pub enum ErrorCode {
// Existing error codes
GoalNotMet,
}
Updates

Appeal created

bube Lead Judge 5 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.