RustFund

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

Missing Contribution Amount Update

Summary

The contract fails to update contribution account records with the amount contributed, causing a severe accounting issue.

Vulnerability Details

In the contribute function, the contract properly transfers SOL from the contributor to the fund account, but it doesn't update the individual contribution record with the amount contributed. While the function initializes a new contribution account, it sets the amount to 0 but never updates it with the actual contribution amount

// Initialize or update contribution record
if contribution.contributor == Pubkey::default() {
contribution.contributor = ctx.accounts.contributor.key();
contribution.fund = fund.key();
contribution.amount = 0; // Sets amount to 0, but never updates it
}
​
// Transfer SOL from contributor to fund account
let cpi_context = CpiContext::new(
ctx.accounts.system_program.to_account_info(),
system_program::Transfer {
from: ctx.accounts.contributor.to_account_info(),
to: fund.to_account_info(),
},
);
system_program::transfer(cpi_context, amount)?;
fund.amount_raised += amount; // Updates total but not individual record

Impact

This vulnerability allows users to potentially refund multiple times for the same contribution, or refund more than they contributed, creating a significant risk of fund depletion.

POC

Add to tests/rustfund.ts:

//audit HIGH - Missing Contribution Amount Update
it("Shows contribution amount not recorded", async () => {
// Generate PDA for contribution
[contributionPDA, contributionBump] = await PublicKey.findProgramAddress(
[fundPDA.toBuffer(), provider.wallet.publicKey.toBuffer()],
program.programId
);
​
await program.methods
.contribute(contribution)
.accounts({
fund: fundPDA,
contributor: provider.wallet.publicKey,
contribution: contributionPDA,
systemProgram: anchor.web3.SystemProgram.programId,
})
.rpc();
​
const contributionAccount = await program.account.contribution.fetch(contributionPDA);
console.log(`Contributed ${contribution.toString()} lamports`);
console.log(`Recorded contribution amount: ${contributionAccount.amount.toString()}`);
});

Output:

========================================
šŸ› BUG REPORT [HIGH]: Missing Contribution Amount Update
----------------------------------------
Description: Contribution amounts are not recorded in the contribution account, allowing multiple refunds of the same contribution
Evidence: Contributed 500000000 lamports, but recorded contribution amount is: 0
========================================

Tools Used

  • Anchor framework for testing

  • Manual code review

Recommendations

Update the contribution amount in the contribute function:

// Initialize or update contribution record
if contribution.contributor == Pubkey::default() {
contribution.contributor = ctx.accounts.contributor.key();
contribution.fund = fund.key();
contribution.amount = 0;
}
​
// Transfer SOL from contributor to fund account
let cpi_context = CpiContext::new(
ctx.accounts.system_program.to_account_info(),
system_program::Transfer {
from: ctx.accounts.contributor.to_account_info(),
to: fund.to_account_info(),
},
);
system_program::transfer(cpi_context, amount)?;
​
// Update the contribution amount with the new amount
+ contribution.amount += amount;
fund.amount_raised += amount;
Updates

Appeal created

bube Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Contribution amount is not updated

Support

FAQs

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