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 { assert, expect } from 'chai';
describe("PoC", () => {
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = anchor.workspace.Rustfund as Program<Rustfund>;
const creator = provider.wallet;
const otherUser = anchor.web3.Keypair.generate();
const otherUser2 = anchor.web3.Keypair.generate();
const otherUser3 = anchor.web3.Keypair.generate();
const fundName = "firstflight Fund";
const description = "this program is for firstflight";
const goal = new anchor.BN(1000000000);
const contribution = new anchor.BN(500000000);
const deadline = new anchor.BN(Math.floor(Date.now() / 1000) + 10);
let fundPDA: PublicKey;
let fundBump: number;
let contributionPDA: PublicKey;
let contributionBump: number;
before(async () => {
[fundPDA, fundBump] = await PublicKey.findProgramAddress(
[Buffer.from(fundName), creator.publicKey.toBuffer()],
program.programId
);
});
it("Creates a fund", async () => {
await program.methods
.fundCreate(fundName, description, goal)
.accounts({
fund: fundPDA,
creator: creator.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.rpc();
const fund = await program.account.fund.fetch(fundPDA);
console.log("fundName", fund.name);
console.log("fundDescription", fund.description);
console.log("fundGoal", fund.goal);
console.log("fundCreator", fund.creator);
console.log("fundAmountRaised", fund.amountRaised);
});
it("Sets a deadline", async () => {
await program.methods
.setDeadline(deadline)
.accounts({
fund: fundPDA,
creator: creator.publicKey,
})
.rpc();
const fund = await program.account.fund.fetch(fundPDA);
console.log("fundDeadline", fund.deadline);
});
it("Contributes to fund", async () => {
[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 fund = await program.account.fund.fetch(fundPDA);
const contributionAccount = await program.account.contribution.fetch(contributionPDA);
console.log("fundBalanceAfter", await provider.connection.getBalance(fundPDA));
assert(contributionAccount.amount.toNumber()==0)
});
})
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; // @audit - user's contribution amount is not being updated
+ contribution.amount += amount;
Ok(())
}