RustFund

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

No Check if Goal is Reached Before Allowing Refunds

Summary

A critical vulnerability exists in the refund mechanism of the Solana crowdfunding contract where the contract does not verify if the fundraising goal has been reached before processing refunds, potentially undermining the intended fundraising model and creating opportunities for premature fund withdrawal.

Vulnerability Details

The vulnerable code segment reveals a fundamental flaw in the refund logic:

  • No verification if fundraising goal is reached

  • Allows refunds regardless of fund's success status

  • Breaks the documentation

  • Enables manipulation of fundraising mechanisms

pub fn refund(ctx: Context<FundRefund>) -> Result<()> {
let amount = ctx.accounts.contribution.amount;
if ctx.accounts.fund.deadline != 0 && ctx.accounts.fund.deadline > Clock::get().unwrap().unix_timestamp.try_into().unwrap() {
return Err(ErrorCode::DeadlineNotReached.into());
}
// Transfers funds back to contributor
**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.contributor.to_account_info().try_borrow_mut_lamports()? =
ctx.accounts.contributor.to_account_info().lamports()
.checked_add(amount)
.ok_or(ErrorCode::CalculationOverflow)?;
// Reset contribution amount
ctx.accounts.contribution.amount = 0;
Ok(())
}

Impact

  • Contributors can withdraw funds even if the goal is successful

  • Breaks the standard crowdfunding model of goal-based funding

  • Compromises the integrity of the fundraising platform

  • Creating uncertainty in fundraising outcomes

  • Potential abuse of the refund mechanism

Recommendations

Immediate and comprehensive recommendations include:

  1. Implement Goal Verification

pub fn refund(ctx: Context<FundRefund>) -> Result<()> {
let fund = &ctx.accounts.fund;
let contribution = &ctx.accounts.contribution;
// Check if deadline is reached
if fund.deadline != 0 && fund.deadline > Clock::get().unwrap().unix_timestamp.try_into().unwrap() {
return Err(ErrorCode::DeadlineNotReached.into());
}
// Verify fundraising goal was NOT reached
if fund.amount_raised >= fund.goal {
return Err(ErrorCode::FundingGoalReached.into());
}
// Existing refund logic remains the same
// ...
}

Tools Used

  • Manual code review

  • Static code analysis

Updates

Appeal created

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

There is no check for goal achievement in `refund` function

Support

FAQs

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