RustFund

First Flight #36
Beginner FriendlyRust
100 EXP
View results
Submission Details
Severity: high
Invalid

Reentrancy Attack through direct SOL transfer in `lib.rs::refund()` function

Summary

Even though Reentrancy attacks are less in Solana still it is possible to do. Since Solana allows Cross-Program Invocations (CPI), an attacker could create a malicious program that triggers refund multilpe times.

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

CEI pattern is not followed properly in this function lib.rs::refund()

**ctx.accounts.contributor.to_account_info().try_borrow_mut_lamports()? =
ctx.accounts.contributor.to_account_info().lamports()
.checked_add(amount)
.ok_or(ErrorCode::CalculationOverflow)?;
// Reset contribution amount after refund
ctx.accounts.contribution.amount = 0;

Vulnerability Details

The root cause lies in updating the amount variable after the SOL transfers.

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

Impact

Contributer can take over the entire SOL funds contributions of other contributors.

Tools Used

Manual Review

Recommendations

Update the below logic in lib.rs::refund() function

@> + ctx.accounts.contribution.amount = 0;
**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)?;
// Reset contribution amount after refund
@> - ctx.accounts.contribution.amount = 0;
Updates

Appeal created

bube Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

[Invalid] Reentrancy in refund

The reentrancy risk on Solana is highly eliminated. The `try_borrow_mut_lamports` ensures that only one reference to an account exists at a time. Also, once the fund’s lamports are borrowed mutably, no other transaction can modify them until the borrow is released. This means the function will reset the `amount` before the next call.

Support

FAQs

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