Summary
The contract deducts lamports during refunds but doesn't reduce the amount_raised counter, creating a discrepancy between actual funds and displayed totals.
Vulnerability Details
The fund.amount_raised field acts as a deposit counter but never decreases, while real funds are reduced via lamport transfers.
https://github.com/CodeHawks-Contests/2025-03-rustfund/blob/b5dd7b0ec01471667ae3a02520701aae405ac857/programs/rustfund/src/lib.rs#L66-L88
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;
    
    Ok(())
}
Impact
- Withdrawal Failures: Creators may attempt withdrawals exceeding actual balances. 
- False Progress: Funding goals appear closer to completion than reality. 
- Trust Erosion: Users see inflated totals that don't match blockchain reality. 
Tools Used
Recommendations
Add to refund() after lamport transfer
let fund = &mut ctx.accounts.fund;  
fund.amount_raised = fund.amount_raised  
    .checked_sub(amount)  
    .ok_or(ErrorCode::CalculationOverflow)?;  
Add validation in withdraw()