M-04. Missing Maximum Value Validation
Severity: Medium
Category: Input Validation / Arithmetic Safety
Summary
The RustFund protocol accepts arbitrarily large values (up to the maximum u64
value) for campaign goals without validation, risking arithmetic overflow and unrealistic fund scenarios.
Vulnerability Details
The fundCreate
function in lib.rs
lacks input validation for the campaign goal, permitting extremely high goals (up to 18446744073709551615
, the maximum value for a u64
).
Affected Component:
-
File: lib.rs
-
Function: fundCreate
The vulnerability arises due to the absence of checks to enforce realistic maximum limits:
pub fn fund_create(ctx: Context<FundCreate>, name: String, description: String, goal: u64) -> Result<()> {
let fund = &mut ctx.accounts.fund;
fund.goal = goal;
Ok(())
}
Impact
-
Possibility of arithmetic overflow in calculations involving large campaign goals.
-
Creation of economically impossible or nonsensical campaigns.
-
Risk of financial and accounting inconsistencies.
Proof of Concept (PoC)
const MAX_U64 = BigInt('18446744073709551615');
await program.methods
.fundCreate(
FUND_NAME,
"Max value test",
new anchor.BN(MAX_U64.toString())
)
.accounts({ fund: fund1, creator: creator.publicKey, systemProgram: SystemProgram.programId })
.signers([creator])
.rpc();
const fundData = await program.account.fund.fetch(fund1);
console.log(`Fund goal: ${fundData.goal.toString()}`);
console.log(`Fund goal equals MAX_U64: ${fundData.goal.toString() === MAX_U64.toString()}`);
Creating fund with near-maximum goal...
Fund created with MAX_U64 goal
Checking if creation succeeded by fetching fund data...
Fund goal: 18446744073709551615
Fund goal equals MAX_U64: true
No maximum value validation on fund goal
*/
Tools Used
-
Manual Review
-
Anchor Framework
Recommendations
Implement input validation in fundCreate
to enforce realistic campaign goals:
+ pub const MAX_GOAL_AMOUNT: u64 = 1_000_000_000 * LAMPORTS_PER_SOL; // Example maximum (1B SOL)
pub fn fund_create(ctx: Context<FundCreate>, name: String, description: String, goal: u64) -> Result<()> {
+ require!(goal <= MAX_GOAL_AMOUNT, ErrorCode::GoalTooLarge);
let fund = &mut ctx.accounts.fund;
fund.goal = goal;
// other initialization logic...
Ok(())
}
// Add error code
#[error_code]
pub enum ErrorCode {
+ #[msg("Goal amount exceeds maximum allowed")]
+ GoalTooLarge,
}