RustFund

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

contribution.amount is never updated in the function contribute

Summary

contribution.amount is meant to keep track of contributor's
contributions but never gets updated and stays zero.

Vulnerability Details

In the function pub fn contribution (line 25 - 52)

pub fn contribute(ctx: Context<FundContribute>, amount: u64) -> Result<()> {
let fund = &mut ctx.accounts.fund;
let contribution = &mut ctx.accounts.contribution;
if fund.deadline != 0 && fund.deadline < Clock::get().unwrap().unix_timestamp.try_into().unwrap() {
return Err(ErrorCode::DeadlineReached.into());
}
// 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)?;
fund.amount_raised += amount;
Ok(())
}

the value for contribution.amount only gets initialized(line 37) but never updated.

Impact

This vulnerability affects contributor when they want a refund. Since amount is zero the contributor will never be able to claim a refund.

Tools Used

Manual code review.

Recommendations

Add this to update contribution.amount after line 48

pub fn contribute(ctx: Context<FundContribute>, amount: u64) -> Result<()> {
//...
contribution.amount = contribution.amount.checked_add(amount).ok_or(ErrorCode::CalculationOverflow)?;
//...
}

POC

Add this to ./tests/rustfund.ts

it("Test contribution dot amount", async () => {
// Generate PDA for contribution
[contributionPDA, contributionBump] = await PublicKey.findProgramAddress(
[fundPDA.toBuffer(), otherUser.publicKey.toBuffer()],
program.programId
);
const airdropSig = await provider.connection.requestAirdrop(
otherUser.publicKey,
2 * anchor.web3.LAMPORTS_PER_SOL
);
await provider.connection.confirmTransaction(airdropSig);
// make contribution twice
//first contribution
await program.methods
.contribute(contribution)
.accounts({
fund: fundPDA,
contributor: otherUser.publicKey,
contribution: contributionPDA,
system_Program: anchor.web3.SystemProgram.programId,
})
.signers([otherUser])
.rpc();
//second contribution
await program.methods
.contribute(contribution)
.accounts({
fund: fundPDA,
contributor: otherUser.publicKey,
contribution: contributionPDA,
system_Program: anchor.web3.SystemProgram.programId,
})
.signers([otherUser])
.rpc();
const fund = await program.account.fund.fetch(fundPDA);
const contributionAccount = await program.account.contribution.fetch(contributionPDA);
console.log("fundBalanceAfter", await provider.connection.getBalance(fundPDA));
console.log("contributorAmount", contributionAccount.amount.toNumber());
});

Will output

fundBalanceAfter 1037590960
contributorAmount 0
Test contribution dot amount (1259ms)

The test demonstrate that contribution.amount never gets updated.

Updates

Appeal created

bube Lead Judge 7 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.