RustFund

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

An attacker can DOS the contract's withdraw functionality

Summary

Assuming that accounting contribution.amount increment is fixed in the contribute() function.
The core issue lies in the refund function:

  • When a contributor refunds their contribution (contribution.amount), the lamports are transferred back from the fund account to the contributor.

  • However, fund.amount_raised is not decremented to reflect this withdrawal.

  • This creates a mismatch between:

    • fund.amount_raised: The program's internal record of total contributions.

    • fund.lamports(): The actual SOL balance in the fund account.

    • In refund:

      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());
      }
      **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)?;
      ctx.accounts.contribution.amount = 0; // Resets contribution, but not fund.amount_raised is not decremented
      Ok(())
      }

From the following code we can see that the contribution amount of the refunding amount is set to zero but the amount_raised is not.
this will mean that we will try to do balanceOfThiscontract - amount_raised which is not possible as clearly amount_raised would have a much greater value than balanceOfThisAddress.

Vulnerability Details

  1. Assume that the fund already some amount of Sol, let's say 100 Sol, with the creator Being Bob

  2. Now Alice contributed 100 more Sol to the fund, making the total balance of the address being 200 also fund.amount_raised will be 200

  3. Alice immediately withdraws her funding by calling refund

  4. The actual balance of the fund would be 100Sol and the fund.amount_raised would still be 200

  5. This will create a disrepency between the actual balance and the fund.amount_raised.

Impact

The previous contributors and owner cannot take thier fund out and the funds will be stuck.

Tools Used

manual analysis

Mitigation

This can be fixed by account for the decreament of fund.amount_raised in any withdraw functions.

Updates

Appeal created

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