RustFund

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

Funds stuck due to withdrawal of total amount_raised or not resseting amount_raised after each withdraw

Summary

The withdraw function attempts to transfer the entire amount_raised value from the fund account to the creator account, regardless of the actual lamport balance available in the fund.

Vulnerability Details

In the withdraw function, since amount_raised is not reset after a withdrawal and continues to accumulate with new contributions, subsequent withdrawal attempts may fail when the requested amount exceeds the current balance. This can leave contributed funds inaccessible if no further contributions increase the balance to match or exceed amount_raised.

Impact

In scenarios where the creator withdraws an initial amount (e.g., 1000 lamports) and new contributions are added (e.g., 500 lamports), the function tries to withdraw the total amount_raised (1500 lamports) despite only 500 lamports being available. This results in a transaction failure due to insufficient funds, leaving the 500 lamports stuck in the fund account

Tools Used

manual code review

Recommendations

To resolve this issue and ensure all contributed funds can be withdrawn without getting stuck, modify the withdraw function to:

  1. Transfer the current lamport balance of the fund account instead of amount_raised.

  2. Reset amount_raised to 0 after each withdrawal to maintain state consistency.

  3. Include a check to prevent unnecessary withdrawals when no funds are available.

pub fn withdraw(ctx: Context<FundWithdraw>) -> Result<()> {
let fund_account = ctx.accounts.fund.to_account_info();
let creator_account = ctx.accounts.creator.to_account_info();
// Get the current lamport balance of the fund account
let amount = fund_account.lamports();
// Prevent withdrawal if no funds are available
if amount == 0 {
return Err(ErrorCode::NoFundsToWithdraw.into());
}
// Transfer all available lamports to the creator
**fund_account.try_borrow_mut_lamports()? = 0;
**creator_account.try_borrow_mut_lamports()? += amount;
// Reset amount_raised to reflect the new balance
ctx.accounts.fund.amount_raised = 0;
Ok(())
}

add this error code

#[error_code]
pub enum ErrorCode {
#[msg("Deadline already set")]
DeadlineAlreadySet,
#[msg("Deadline reached")]
DeadlineReached,
#[msg("Deadline not reached")]
DeadlineNotReached,
#[msg("Unauthorized access")]
UnauthorizedAccess,
#[msg("Calculation overflow occurred")]
CalculationOverflow,
+ #[msg("No funds available to withdraw")]
+ NoFundsToWithdraw,
}
Updates

Appeal created

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

`amount_raised` is not reset to 0 in `withdraw` function

Support

FAQs

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