RustFund

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

Unadjusted amount_raised on Refund

Summary

The refund function fails to adjust the amount_raised value in the Fund account when a refund is processed. This leads to inaccurate tracking of raised funds, enabling potential double refunds and false reporting of campaign success.

Vulnerability Details

  • While the refund transfers SOL back to the contributor, the amount_raised value in the Fund is not reduced.

  • This causes incorrect accounting, where amount_raised still reflects refunded contributions.

  • Contributors could potentially request refunds multiple times, as the contract does not properly adjust the total.

Proof of Concept

  • Alice contributes 5 SOL to a campaign.

  • amount_raised = 5 SOL.

  • Alice requests a refund and gets 5 SOL back.

    • However, amount_raised remains at 5 SOL instead of decreasing to 0 SOL.

  • The campaign falsely appears funded when it actually has fewer funds.

  • Potential exploit: Alice might call refund() multiple times since her contribution record is reset without updating the fund balance.

The Impacted Code

// Current unsafe implementation:
pub fn refund(ctx: Context<FundRefund>) -> Result<()> {
let amount = ctx.accounts.contribution.amount;
**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)?;
// Contribution amount is reset, but fund total remains unchanged!
ctx.accounts.contribution.amount = 0;
Ok(())
}

Impact

  • Campaigns appear more funded than they actually are, breaking transparency.

  • Double-refund exploits could be possible, as funds are refunded without adjusting amount_raised.

  • Creators might withdraw non-existent funds, thinking the campaign was fully funded.

Tools Used

Manual code review

Recommendations

To fix this issue, the amount_raised value must be decreased when a refund is processed:

fund.amount_raised = fund.amount_raised.checked_sub(amount)
.ok_or(ErrorCode::CalculationOverflow)?;
Updates

Appeal created

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

`amount_raised` not updated in `refund` function

Support

FAQs

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