Summary
The contract checks for a flag that prevents setting multiple deadlines, but it never actually sets this flag.
Vulnerability Details
In the set_deadline function, the contract checks the dealine_set flag to prevent setting the deadline multiple times, but after setting the deadline, it never updates this flag to true. This means the check is ineffective, and deadlines can be changed multiple times.
pub fn set_deadline(ctx: Context<FundSetDeadline>, deadline: u64) -> Result<()> {
let fund = &mut ctx.accounts.fund;
if fund.dealine_set {
return Err(ErrorCode::DeadlineAlreadySet.into());
}
fund.deadline = deadline;
Ok(())
}
Impact
Fund creators can change the deadline multiple times, creating confusion for contributors and potentially manipulating the funding timeline
POC
it("Can set multiple deadlines despite check", async () => {
const firstDeadline = new anchor.BN(Math.floor(Date.now() / 1000) + 100);
await program.methods
.setDeadline(firstDeadline)
.accounts({
fund: fundPDA,
creator: creator.publicKey,
})
.rpc();
ā
const secondDeadline = new anchor.BN(Math.floor(Date.now() / 1000) + 200);
await program.methods
.setDeadline(secondDeadline)
.accounts({
fund: fundPDA,
creator: creator.publicKey,
})
.rpc();
ā
const fund = await program.account.fund.fetch(fundPDA);
console.log(`Set deadline twice. New deadline: ${fund.deadline.toString()}`);
});
Output:
========================================
š BUG REPORT [MEDIUM]: Deadline Flag Never Set
----------------------------------------
Description: The dealine_set flag is checked but never set to true after setting a deadline
Evidence: Successfully set deadline multiple times. New deadline: 1742920083
========================================
Tools Used
Recommendations
pub fn set_deadline(ctx: Context<FundSetDeadline>, deadline: u64) -> Result<()> {
let fund = &mut ctx.accounts.fund;
if fund.dealine_set {
return Err(ErrorCode::DeadlineAlreadySet.into());
}
fund.deadline = deadline;
+ fund.dealine_set = true; // Add this line
Ok(())
}