The rustfund smart contract includes a goal field in the Fund account intended to represent the target fundraising amount. However, this field is never used in the program’s logic, rendering it ineffective. This vulnerability allows the contract to operate without enforcing critical crowdfunding constraints, such as stopping contributions once the goal is reached or restricting withdrawals unless the goal is met. This oversight undermines the contract’s intended functionality and exposes users to potential misuse by the creator.
In the fund_create function, the goal parameter (type u64) is assigned to the fund.goal field of the Fund account
Despite being stored fund.goal is not referenced anywhere else in the program, including key functions like contribute withdraw refund, or set_deadline. This lack of enforcement means:
Contributions can exceed the goal without restriction.
The creator can withdraw all funds (amount_raised) at any time, even if the goal isn’t met.
Refunds are triggered solely by the deadline, ignoring whether the goal was achieved.
This contradicts the typical expectations of a crowdfunding mechanism, where the goal should influence operational logic (e.g., success/failure conditions). The absence of such checks suggests an incomplete implementation or a critical design flaw.
Affected Lines of Code:
Consider the following scenario:
A creator initializes a fund with:
name = "Project X"
description = "Raise funds for X"
goal = 100 SOL
deadline = 0 (unset initially) Using: fund_create(ctx, "Project X", "Raise funds for X", 100).
Contributors invoke contribute multiple times, raising fund.amount_raised to 150 SOL (exceeding the goal).
No check in contribute stops this:
fund.amount_raised += amount; executes regardless of fund.goal.
The creator calls withdraw before setting a deadline:
withdraw transfers all 150 SOL to the creator’s account (ctx.accounts.creator), despite the goal being only 100 SOL, because no condition like if fund.amount_raised < fund.goal exists.
This demonstrates that fund.goal has no bearing on the contract’s behavior, allowing overfunding and premature withdrawals.
The unutilized fund.goal has significant consequences:
User Trust: Contributors expect a crowdfunding campaign to respect its stated goal. Without enforcement, they may overfund a project unnecessarily or lose funds to a creator who withdraws early, eroding trust in the platform.
Financial Risk: Contributors have no guarantee that the project adheres to its fundraising target. A malicious creator could set a low goal (e.g., 1 SOL), collect far more, and withdraw everything without justification.
Contract Integrity: The lack of goal enforcement undermines the contract’s purpose as a crowdfunding tool, potentially leading to legal or reputational issues for the deploying entity.
manual Review
To mitigate this vulnerability, integrate fund.goal into the contract’s logic as follows:
Cap Contributions: Modify contribute to prevent overfunding:
Add to ErrorCode enum: GoalExceeded
Restrict Withdrawals: Ensure the creator can only withdraw if the goal is met
Add to ErrorCode enum: GoalNotReached,.
Enhance Refunding Logic: Allow refunds if the deadline passes and the goal isn’t met
Add to ErrorCode enum: GoalReached,
Typically the crowdfunding campaigns allow contribution after the goal is achieved. This is normal, because the goal is the campaign to raise as much as possible funds. Therefore, this is a design choice.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.