Rust Fund

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

Fund name max length conflicts with PDA seed limit

Fund name max length conflicts with PDA seed limit

Description

The Fund account schema allows fund names up to 200 bytes with #[max_len(200)]. This suggests that users should be able to create funds with names up to that length.

However, fund_create derives the fund PDA using the full name.as_bytes() as a PDA seed. Solana PDA seeds are limited to 32 bytes per seed. Therefore, any fund name longer than 32 bytes cannot be used to derive the fund PDA, even though the account schema allows up to 200 bytes.

#[derive(Accounts)]
#[instruction(name: String)]
pub struct FundCreate<'info> {
#[account(
init,
payer = creator,
space = 8 + Fund::INIT_SPACE,
@> seeds = [name.as_bytes(), creator.key().as_ref()],
bump
)]
pub fund: Account<'info, Fund>,
#[account(mut)]
pub creator: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
#[derive(InitSpace)]
pub struct Fund {
@> #[max_len(200)]
pub name: String,
#[max_len(5000)]
pub description: String,
pub goal: u64,
pub deadline: u64,
pub creator: Pubkey,
pub amount_raised: u64,
pub dealine_set: bool,
}

Risk

Likelihood:

  • This occurs for every fund name longer than 32 bytes because the name is used directly as a PDA seed.

  • The account schema permits names up to 200 bytes, so valid-looking inputs can still fail during PDA derivation.

Impact:

  • Users cannot create funds with names longer than 32 bytes despite the program allocating account space for names up to 200 bytes.

  • Frontends or integrations that trust the account schema may accept fund names that the program cannot support.

Proof of Concept

it("fund name max length is inconsistent with PDA seed limit", async () => {
const testCreator = provider.wallet;
const longName = "a".repeat(33);
let derivationFailed = false;
try {
await PublicKey.findProgramAddress(
[Buffer.from(longName), testCreator.publicKey.toBuffer()],
program.programId
);
} catch (err) {
derivationFailed = true;
expect(String(err)).to.include("Max seed length");
}
expect(longName.length).to.be.lessThanOrEqual(200);
expect(derivationFailed).to.eq(true);
});

The test uses a 33-byte name, which is below the declared #[max_len(200)] but above the 32-byte PDA seed limit. PDA derivation fails with Max seed length.

Recommended Mitigation

Do not use the full variable-length name as a PDA seed. Either enforce a 32-byte maximum name length or derive the PDA from a fixed-length hash of the name.

- #[max_len(200)]
+ #[max_len(32)]
pub name: String,

Alternatively:

- seeds = [name.as_bytes(), creator.key().as_ref()],
+ let name_hash = anchor_lang::solana_program::hash::hash(name.as_bytes());
+ seeds = [name_hash.as_ref(), creator.key().as_ref()],

If a hash is used for PDA derivation, store the original full name in the account and consider adding uniqueness/collision handling appropriate for the protocol.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 23 hours 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!