Rust Fund

AI First Flight #9
Beginner FriendlyRust
EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Improper Access Control in Refund and Withdraw Functions

  1. Relevant GitHub Links
    https://github.com/CodeHawks-Contests/2025-03-rustfund/blob/b5dd7b0ec01471667ae3a02520701aae405ac857/programs/rustfund/src/lib.rs#L66

https://github.com/CodeHawks-Contests/2025-03-rustfund/blob/b5dd7b0ec01471667ae3a02520701aae405ac857/programs/rustfund/src/lib.rs#L90

  1. Summary
    The contract’s refund and withdraw functions do not enforce the conditions outlined in the documentation. Refunds are allowed if the deadline is unset or passed, without checking the goal, and creators can withdraw funds at any time, even if the goal isn’t met. Additionally, the amount_raised value isn’t updated during refunds, which can lock funds and cause withdraw failures.

  2. Vulnerability Details
    The documentation states that refunds should only occur after the deadline if the goal isn’t met, and withdrawals should only be allowed after the campaign succeeds (goal is met).

Refund Mechanism: Contributors can get refunds if deadlines are reached and goals aren't met

Secure Withdrawals: Creators can withdraw funds once their campaign succeeds

However:

In the refund function, there’s no check for the goal. Refunds proceed if the deadline is unset or passed.

In the withdraw function, there’s no goal check either, allowing creators to withdraw funds anytime.

Another issue: refund doesn’t subtract the refunded amount from fund.amount_raised. Since withdraw uses amount_raised to determine the withdrawal amount, this can lead to failures if the actual balance is lower, locking the funds.

  1. Impact
    Contributors can be refunded even when they shouldn’t be, undermining the campaign’s integrity.

Creators can withdraw funds prematurely, potentially stealing contributions.

Funds can become locked due to the mismatch between amount_raised and the actual balance, preventing legitimate withdrawals.

  1. Tools Used
    Manual Code Review and Foundry

  2. Recommended Mitigation
    Add goal checks to both functions and update amount_raised during refunds:

For refund: Ensure it only works if the deadline is set, passed, and the goal isn’t met.

For withdraw: Allow withdrawals only if the goal is met.

Subtract refunded amounts from fund.amount_raised.

pub fn refund(ctx: Context) -> 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() {

  • if ctx.accounts.fund.deadline != 0 && ctx.accounts.fund.deadline > Clock::get().unwrap().unix_timestamp.try_into().unwrap() || !ctx.accounts.fund.dealine_set {
    return Err(ErrorCode::DeadlineNotReached.into());
    }

  • if ctx.accounts.fund.goal ) -> Result<()> {
    let amount = ctx.accounts.fund.amount_raised;

  • if ctx.accounts.fund.goal > ctx.accounts.fund.amount_raised {

  •   return Err(ErrorCode::GoalNotReached.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.creator.to_account_info().try_borrow_mut_lamports()? =
    ctx.accounts.creator.to_account_info().lamports()
    .checked_add(amount)
    .ok_or(ErrorCode::CalculationOverflow)?;

    Ok(())
    }

    #[error_code]
    pub enum ErrorCode {
    #[msg("Deadline already set")]
    DeadlineAlreadySet,
    #[msg("Deadline reached")]
    DeadlineReached,
    #[msg("Deadline not reached")]
    DeadlineNotReached,
    #[msg("Unauthorized access")]
    UnauthorizedAccess, // @question : 사용 안되는데?
    #[msg("Calculation overflow occurred")]
    CalculationOverflow,

  • #[msg("Goal Not Reached")]

  • GoalNotReached,
    }

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 3 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!