Summary
The withdraw function lacks checks for campaign success, allowing fund creators to withdraw contributions before the funding goal is met.
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
Malicious creator can withdraw funds before campaing success. Resulting in loss of funds for contributors
Tools Used
N/A
Recommendations
Enforce the following checks in withdraw:
let now = Clock::get()?.unix_timestamp as u64;
require!(fund.deadline != 0 && now >= fund.deadline, ErrorCode::DeadlineNotReached);
require!(fund.amount_raised >= fund.goal, ErrorCode::GoalNotReached);