Rust Fund

AI First Flight #9
Beginner FriendlyRust
EXP
View results
Submission Details
Impact: low
Likelihood: high
Invalid

Fund names longer than 32 bytes can never create a fund — name is used directly as a PDA seed

Description

Fund.name is declared with a 200-byte limit, but the raw name bytes are used as a PDA seed in both FundCreate and FundWithdraw (programs/rustfund/src/lib.rs):

#[account]
#[derive(InitSpace)]
pub struct Fund {
#[max_len(200)]
pub name: String,
...
}
// FundCreate
#[account(init, payer = creator, space = 8 + Fund::INIT_SPACE,
seeds = [name.as_bytes(), creator.key().as_ref()], bump)]
pub fund: Account<'info, Fund>,
// FundWithdraw
#[account(mut, seeds = [fund.name.as_bytes(), creator.key().as_ref()], bump, has_one = creator)]
pub fund: Account<'info, Fund>,

Solana limits each individual PDA seed to 32 bytes (MAX_SEED_LEN). Any name longer than that makes address derivation fail before the instruction runs.

Risk

Impact: Low — no funds are at risk; fund_create simply fails for any name over 32 bytes, so the advertised 200-byte limit is unreachable and misleading. Names with multi-byte characters hit the limit at far fewer visible characters (e.g. ~16 Cyrillic letters, ~10 CJK characters). Account space is also over-allocated by 168 bytes per fund for a field that can never be filled.

Likelihood: High — any campaign title longer than a few words triggers it; the project's own test uses a 16-byte name and therefore never hits the limit.

Proof of Concept

Test from tests/poc.ts:

it("F8 [Low]: names longer than 32 bytes can never create a fund (PDA seed limit)", async () => {
const longName = "A".repeat(40); // well within #[max_len(200)]
let err = "";
try {
const f = fundPda(longName, creator.publicKey); // findProgramAddressSync
await send(ixFundCreate(f, creator.publicKey, longName, "d", GOAL), creator);
} catch (e: any) { err = String(e.message ?? e); }
expect(err).to.not.equal("");
});

Output:

fund_create("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") → Max seed length exceeded
✔ F8 [Low]: names longer than 32 bytes can never create a fund (PDA seed limit)

Recommended Mitigation

Do not use free-form text as a seed. Either hash the name:

use anchor_lang::solana_program::hash::hash;
seeds = [hash(name.as_bytes()).as_ref(), creator.key().as_ref()]

or derive the PDA from a per-creator counter / caller-supplied nonce, and keep the full name only in account data. Alternatively, lower #[max_len] to 32 and document the limit.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 1 hour ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!