Rust Fund

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

Unchecked Arithmetic Overflow on amount_raised

[M-01] Unchecked Arithmetic Overflow on amount_raised

Description

  • The contribute() function increments fund.amount_raised to track total contributions. Financial state variables should use checked arithmetic to prevent silent overflow.

  • Line 50 uses direct += addition without checked_add(). In Rust release builds without overflow-checks = true, integer overflow wraps silently. While the workspace Cargo.toml has overflow-checks enabled, defense-in-depth mandates explicit checked arithmetic for financial state.

@> fund.amount_raised += amount; // unchecked addition

Risk

Likelihood: Low

  • The workspace Cargo.toml has overflow-checks = true for the release profile, mitigating this in standard builds. The risk is conditional on Anchor build profiles not inheriting this setting.

Impact: High

  • Massive contributions could wrap amount_raised to near-zero, allowing the creator to claim the campaign failed while having received enormous funds.

Severity: Medium

Proof of Concept

The += operator uses wrapping arithmetic when overflow-checks is disabled. If the Anchor build profile does not inherit the workspace-level overflow-checks setting, a contribution of u64::MAX - current + 1 wraps amount_raised to near-zero.

it("Proves unchecked overflow wraps amount_raised", async () => {
// This test demonstrates the logical issue — actual overflow depends on build profile
await program.methods.fundCreate("poc-m001", "test", goal).rpc();
await program.methods.setDeadline(deadline1y).rpc();
// First contribution sets amount_raised to a normal value
await program.methods.contribute(new anchor.BN(10 * LAMPORTS_PER_SOL)).rpc();
let fund = await program.account.fund.fetch(fundPDA);
const amountBefore = fund.amountRaised.toNumber();
// In a vulnerable build, contributing (u64::MAX - amountBefore + 1) would wrap to 0
// The += operation has no checked_add guard in the source code:
// fund.amount_raised += amount; // no .checked_add()
console.log(`amount_raised uses unchecked +=: ${amountBefore}`);
console.log("Defense relies entirely on Cargo.toml overflow-checks, not code-level guards");
});
## Recommended Mitigation
Replace the `+=` operator with `checked_add()` so that an overflow produces an explicit error instead of relying on a Cargo.toml build flag. This restores the invariant that `amount_raised` always equals the true sum of contributions — if the addition exceeds `u64::MAX`, the transaction reverts instead of silently wrapping.
```diff
- fund.amount_raised += amount;
+ fund.amount_raised = fund.amount_raised
+ .checked_add(amount)
+ .ok_or(ErrorCode::CalculationOverflow)?;
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 3 days 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!