The "rustfund" contains a critical vulnerability in the FundContribute function where the contribution amount (contribution.amount) is not updated after a contributor transfers SOL to the fund. While the total amount raised (fund.amount_raised) is correctly incremented, the individual contribution record remains unchanged, defaulting to 0. This bug prevents contributors from receiving refunds in the FundRefund function, as it relies on the contribution.amount value to determine the refundable amount. This vulnerability undermines the contract's refund mechanism, a core feature of crowdfunding systems, potentially leading to loss of funds for contributors.
The vulnerability arises in the FundContribute function, which handles contributions to a fund. When a contributor sends SOL, the contract transfers the amount to the fund account and updates fund.amount_raised, but it fails to update the contribution.amount field in the Contribution account. This field is critical for tracking individual contributions and enabling refunds.
The root cause is the absence of an instruction to increment contribution.amount after the SOL transfer. The code initializes contribution.amount to 0 for new contributions but does not update it with the contributed amount. Below is the relevant snippet from the FundContribute function:
In this snippet:
contribution.amount is set to 0 when the contribution account is first initialized.
After the SOL transfer (system_program::transfer(cpi_context, amount)?), there is no line like contribution.amount += amount; to record the contribution.
Only fund.amount_raised is updated, tracking the aggregate total but not the individual contributor’s stake.
FundRefundThe FundRefund function relies on contribution.amount to determine how much SOL to refund, as shown below:
Since contribution.amount remains 0 due to the bug in FundContribute, the amount variable in FundRefund will always be 0, meaning no SOL is transferred back to the contributor, even when a refund is valid (e.g., after the deadline).
This vulnerability has a severe impact on the contract’s functionality and trustworthiness:
Loss of Funds for Contributors: Contributors cannot reclaim their contributions, even when eligible for a refund (e.g., if the deadline passes and the goal isn’t met). Since contribution.amount is always 0, the refund mechanism transfers no SOL, effectively locking contributors’ funds in the fund account.
The analysis was conducted using the following tools and resources:
Manual Code Review
To address this vulnerability, the following steps are recommended:
Update contribution.amount in FundContribute:
Modify the contribute function to increment contribution.amount after the SOL transfer. Here’s the corrected code snippet:
This ensures contribution.amount reflects the actual amount contributed, enabling accurate refunds.
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.