Summary
The refund function in the rustfund program does not deduct the refunded amount from the amount_raised field of the Fund account.
This oversight can lead to inaccuracies in the total funds raised, allowing the fund creator to potentially withdraw more than the actual contributions.
Vulnerability Details
In the contribute function, amount_raized is increased, and in withdraw, the amount_raized amount is withdrawn.
However, in the refund function, amount_raized is not deducted.
pub fn contribute(ctx: Context<FundContribute>, amount: u64) -> Result<()> {
...
fund.amount_raised += amount;
...
}
pub fn withdraw(ctx: Context<FundWithdraw>) -> Result<()> {
let amount = ctx.accounts.fund.amount_raised;
...
}
Impact
Since amount_raized is not deducted from the refund, users can attempt to withdraw even the refunded funds, and even legitimate users may fail to withdraw.
Tools Used
Manual Review
Recommendations
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;
[+] **ctx.accounts.fund.amount_raised -= amount;
Ok(())
}```