feat: add the create_fund instruction#7
Conversation
|
Warning Review limit reached
More reviews will be available in 28 minutes and 23 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (12)
WalkthroughReplaces the scaffold Changescreate_fund instruction
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
5768bed to
1c435c6
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
1c435c6 to
77b32d1
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@programs/fund/src/instructions/create_fund.rs`:
- Around line 73-89: The validate_params function currently returns generic
error variants that don't distinguish between different validation failures,
making it hard for clients to provide specific feedback. Replace the shared
FundError::FeeTooHigh variant with field-specific error types for
management_fee_bps and performance_fee_bps validations (line 75 and line 79
checks), and similarly replace the generic FundError::NonCanonicalName with
separate error variants for the empty name check (line 83) and the canonical
padding check (line 87). This requires defining new error variants in the
FundError enum to handle each validation failure independently.
In `@programs/fund/tests/test_create_fund.rs`:
- Around line 138-155: The test functions
create_fund_rejects_a_non_canonical_name and
create_fund_rejects_an_all_zero_name currently only verify that the result is an
error. Add explicit assertions after each is_err() check to verify that the fund
account, vault account, and shares account were not created (i.e., they should
not exist in the state). This validates that when name validation fails, the
transaction is properly rolled back atomically and no accounts are left behind.
- Around line 96-111: The assertion in the duplicate create_fund test is too
permissive and accepts any instruction error, potentially missing unrelated
regressions. Instead of only checking that the second send_create_fund call
returns an InstructionError, retrieve and store the fund account state
immediately after the first successful create_fund call, then after the failed
second attempt, retrieve the fund account state again and assert that the bytes
are identical to verify the account state was not modified. This makes the test
specific to the invariant that fund account initialization is protected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5bc58f5e-435e-4110-a806-0d035648b2d4
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (11)
AGENTS.mdAnchor.tomlprograms/fund/Cargo.tomlprograms/fund/src/error.rsprograms/fund/src/instructions.rsprograms/fund/src/instructions/create_fund.rsprograms/fund/src/instructions/initialize.rsprograms/fund/src/lib.rsprograms/fund/src/state.rsprograms/fund/tests/test_create_fund.rsprograms/fund/tests/test_initialize.rs
💤 Files with no reviewable changes (2)
- programs/fund/src/instructions/initialize.rs
- programs/fund/tests/test_initialize.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
programs/**/src/**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
programs/**/src/**/*.rs: Walk every new or modified#[derive(Accounts)]struct through the checklist in@docs/sealevel-attacks.md, confirming each Solana/Anchor attack class is handled (signer, owner, account matching, arbitrary CPI, PDA seeds and canonical bump, duplicate-mutable, init re-entry).
Treat the security checklist at the bottom of@docs/sealevel-attacks.mdas a hard gate — each#[derive(Accounts)]struct should be walked through it explicitly before merging.
Files:
programs/fund/src/instructions.rsprograms/fund/src/error.rsprograms/fund/src/lib.rsprograms/fund/src/state.rsprograms/fund/src/instructions/create_fund.rs
programs/fund/src/instructions.rs
📄 CodeRabbit inference engine (AGENTS.md)
Add
pub mod <name>; pub use <name>::*;toinstructions.rsfor each new instruction.
Files:
programs/fund/src/instructions.rs
{programs/fund/src/lib.rs,Anchor.toml,target/deploy/fund-keypair.json}
📄 CodeRabbit inference engine (AGENTS.md)
Program ID
8FUTArRdDgGDTYbnBMrzB7mBTwLrYpJDTzWY4d62GpCDmust be declared inprograms/fund/src/lib.rs,Anchor.toml's[programs.localnet], and matchtarget/deploy/fund-keypair.json— keep all three in sync viaanchor keys sync.
Files:
Anchor.tomlprograms/fund/src/lib.rs
Anchor.toml
📄 CodeRabbit inference engine (AGENTS.md)
Anchor toolchain must use
package_manager = "bun"(not yarn/npm) inAnchor.toml.
Files:
Anchor.toml
*
⚙️ CodeRabbit configuration file
Focus on providing constructive criticism. Whenever you see a suboptimal approach, suggest more idiomatic or robust alternative(s). Flag potential footguns. Suggest FP alternatives to mutable/imperative code. Point out architectural flaws like leaky abstractions, tight coupling, wrong level of abstraction, poor type modeling, over-abstraction, unclear domain boundaries. Code should generally be organized based on business concerns rather than technical aspects - suggest improvements if you find violations. Point out gaps in test coverage but suggest tests that are not too coupled to the implementation and actually test domain invariants and business logic.
Files:
Anchor.tomlAGENTS.md
programs/fund/src/lib.rs
📄 CodeRabbit inference engine (AGENTS.md)
Add a thin wrapper inside
#[program] mod fundinlib.rsthat calls<name>::handler(ctx, ...)for each new instruction.
Files:
programs/fund/src/lib.rs
programs/fund/tests/**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
programs/fund/tests/**/*.rs: Write integration tests usinglitesvmdirectly from Rust integration tests underprograms/fund/tests/that include the compiled BPF binary viainclude_bytes!, load it withLiteSVM::new(), and constructInstructionusing Anchor-generated types.
Uselitesvmdirectly from Rust integration tests underprograms/fund/tests/instead ofanchor test.
Files:
programs/fund/tests/test_create_fund.rs
**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
Document everything in tracked markdown files (this file,
programs/fund/README.md,programs/fund/SPEC.md, ADRs underadrs/, or a dedicated doc). Agent memory, scratchpads, or.tmp/files do not count as documentation.
Files:
AGENTS.md
⚙️ CodeRabbit configuration file
Focus on the contents of the docs and not on cosmetic things like markdown formatting. We use markdown files for various docs including but not limited to the north star system specification, SPEC.md, the plan for how to get there, ROADMAP.md, guidelines for AI contributors, AGENTS.md, project overview and instructions for human contributors, README.md. Think about the target audience of a document when deciding what comment to leave. For specifications and designs, suggest potential product, architectural, and UI/UX improvements. For plans, suggest changes that would make things more parallelizable and deliverable-focused. For instructions, suggest better rules and guidelines and point out missing instructions. In all cases, flag needless bloat, prefer clear concise writing, and consider the structure of the document and order of the sections
Files:
AGENTS.md
programs/fund/src/instructions/**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
When adding a new instruction, create
programs/fund/src/instructions/<name>.rswith#[derive(Accounts)] pub struct <Name>andpub fn handler(...).
Files:
programs/fund/src/instructions/create_fund.rs
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: data-cartel/fund
Timestamp: 2026-06-18T23:11:32.200Z
Learning: `anchor build` must run before `cargo test` because integration tests use `include_bytes!` to pull the compiled BPF binary at compile time.
Learnt from: CR
Repo: data-cartel/fund
Timestamp: 2026-06-18T23:11:32.200Z
Learning: Run `anchor build` first, then `cargo test --workspace` to ensure tests exercise a fresh binary and report accurate results.
Learnt from: CR
Repo: data-cartel/fund
Timestamp: 2026-06-18T23:11:32.200Z
Learning: Use lowercase commit messages with conventional prefixes (`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`) and explain why in the body.
Learnt from: CR
Repo: data-cartel/fund
Timestamp: 2026-06-18T23:11:32.200Z
Learning: Never add 'Generated with ...' or co-author trailers to commit messages.
Learnt from: CR
Repo: data-cartel/fund
Timestamp: 2026-06-18T23:11:32.200Z
Learning: Use GitButler CLI (`but`) for all version-control write operations (commits, branches, push).
Learnt from: CR
Repo: data-cartel/fund
Timestamp: 2026-06-18T23:11:32.200Z
Learning: Use branch names with format `<type>/<kebab-description>` and always pass an explicit name to `but branch new`.
Learnt from: CR
Repo: data-cartel/fund
Timestamp: 2026-06-18T23:11:32.200Z
Learning: Always succumb to whatever Solana tooling wants — match its version pins, directory layout, env-var conventions, and config defaults rather than fighting them.
Learnt from: CR
Repo: data-cartel/fund
Timestamp: 2026-06-18T23:11:32.200Z
Learning: Anchor-based Solana program named `fund` uses a single on-chain program with a Cargo workspace and TypeScript app/migrations side managed via bun.
🔇 Additional comments (7)
AGENTS.md (1)
75-75: LGTM!Also applies to: 91-91, 125-125
programs/fund/src/state.rs (1)
1-34: LGTM!programs/fund/Cargo.toml (1)
17-30: LGTM!programs/fund/src/lib.rs (1)
10-20: LGTM!programs/fund/src/instructions.rs (1)
1-3: LGTM!programs/fund/tests/test_create_fund.rs (1)
1-89: LGTM!Also applies to: 114-135, 157-249
Anchor.toml (1)
9-9: ✓ Hard-gate Anchor config constraints confirmed:toolchain.package_manager = "bun"is set, and the Program ID8FUTArRdDgGDTYbnBMrzB7mBTwLrYpJDTzWY4d62GpCDmatches betweenAnchor.tomlandprograms/fund/src/lib.rs. The keypair sync should be verified locally viaanchor keys syncto ensure the generatedtarget/deploy/fund-keypair.jsonis current.
Address the CodeRabbit review on #7: - Split the shared `FeeTooHigh` and `NonCanonicalName` variants into field-specific `ManagementFeeTooHigh`, `PerformanceFeeTooHigh`, and `EmptyName`, so a client (and telemetry) can tell which input was rejected. Validation logic is unchanged; only the error codes get more specific. - Harden the duplicate-create test to assert the pre-existing fund stays byte-identical after the rejected re-init, not merely that it errors. - Assert fund/vault/shares accounts are absent after every rejected create (non-canonical name, all-zero name, and the excessive fee), proving the atomic rollback rather than only checking `is_err`.
Address the CodeRabbit review on #7: - Split the shared `FeeTooHigh` and `NonCanonicalName` variants into field-specific `ManagementFeeTooHigh`, `PerformanceFeeTooHigh`, and `EmptyName`, so a client (and telemetry) can tell which input was rejected. Validation logic is unchanged; only the error codes get more specific. - Harden the duplicate-create test to assert the pre-existing fund stays byte-identical after the rejected re-init, not merely that it errors. - Assert fund/vault/shares accounts are absent after every rejected create (non-canonical name, all-zero name, and the excessive fee), proving the atomic rollback rather than only checking `is_err`.
The error split (ManagementFeeTooHigh / PerformanceFeeTooHigh / EmptyName / NonCanonicalName) updated the code but left SPEC.md describing the old collapsed FeeTooHigh and the shared NonCanonicalName. Rewrite create_fund's error conditions to match, so CodeRabbit's field-specific-errors point holds in the spec too, not only the implementation, and spec-code parity is preserved.
31c3c65 to
b8e6057
Compare
Motivation
The fund program needs its first real instruction — creating a fund — as the
foundation that deposits, withdrawals, and NAV accounting build on. This is
split out of the oversized create-fund PR (#3) so the on-chain logic can be
reviewed on its own, and it folds in the CodeRabbit feedback from #3 plus a
multi-model review pass.
Solution
create_fundinstruction: initializes theFundPDA (seeds[b"fund", manager, name], canonical bump cached on-chain), an SPL vaulttoken account, and a shares mint — both with
authority = Fundand the tokenprogram pinned via
Program<Token>.Fund/CreateFundParamsstate.build_fundconstructs the state as astruct literal (a missing field is a compile error) and the handler applies
it with
set_inner.<= 10_000bps, and
namemust be non-empty and canonically zero-padded so twoencodings can't render as the same name.
programs/fund/tests/test_create_fund.rs(perthe repo's test architecture): full happy path asserting Fund/vault/shares
mint state and that stored bumps re-derive the canonical PDAs, plus
rejection paths (over-cap fees, non-canonical and empty names, duplicate
creation / re-init).
8FUTArRdDgGDTYbnBMrzB7mBTwLrYpJDTzWY4d62GpCDtomatch the deploy keypair (
anchor keys sync); AGENTS.md is updated todocument it.
Closes #17
Summary by CodeRabbit
New Features
Configuration
Documentation
Tests