-
Notifications
You must be signed in to change notification settings - Fork 8
fix: prevent undelegation of closed delegated accounts #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix: prevent undelegation of closed delegated accounts #128
Conversation
WalkthroughAdds a new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (3)
🧰 Additional context used🧠 Learnings (1)📚 Learning: 2025-10-15T11:45:25.802ZApplied to files:
🧬 Code graph analysis (1)tests/test_undelegate_close_account.rs (2)
🔇 Additional comments (4)
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 |
|
@GabrielePicco check this out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
src/error.rssrc/processor/fast/undelegate.rstests/test_undelegate_close_account.rs
🧰 Additional context used
🧬 Code graph analysis (1)
tests/test_undelegate_close_account.rs (2)
src/pda.rs (4)
delegation_metadata_pda_from_delegated_account(106-112)delegation_record_pda_from_delegated_account(98-104)fees_vault_pda(149-151)validator_fees_vault_pda_from_validator(153-159)tests/fixtures/accounts.rs (2)
get_delegation_metadata_data(99-105)get_delegation_record_data(54-56)
🔇 Additional comments (4)
src/processor/fast/undelegate.rs (2)
71-71: LGTM! Documentation clearly describes the new early-exit behavior.The step documentation accurately reflects the new pre-check that rejects closed accounts before proceeding with undelegation.
91-95: LGTM! Pre-check correctly identifies and rejects closed accounts.The guard properly detects closed delegated accounts (zero lamports AND empty data) and returns early with a specific error. This prevents invalid cleanup/fee handling downstream, as stated in the PR objectives.
The check is positioned before other validations, which is appropriate because:
- Account state (lamports, data) is publicly readable on Solana, so checking before ownership validation does not leak sensitive information.
- Early exit avoids potential arithmetic errors or state inconsistencies in subsequent logic when operating on a closed account.
- This is distinct from the fast-path at line 166, which handles accounts with empty data but non-zero lamports.
src/error.rs (1)
90-91: LGTM! Error variant is well-defined and follows existing patterns.The
DelegateAccountClosedvariant:
- Uses the next sequential discriminant (41) after
InvalidDelegationRecordData(40)- Has a clear, descriptive error message that matches its usage in the undelegate processor
- Is correctly positioned before
InfallibleError(100)- Will be automatically handled by the
From<DlpError>implementationstests/test_undelegate_close_account.rs (1)
46-139: LGTM! Test environment setup is comprehensive and correctly models the edge case.The setup properly creates the scenario the PR addresses:
- Closed delegated account (0 lamports, empty data) that is still owned by
dlp::id()(lines 66-68)- Valid delegation_record and delegation_metadata PDAs
- All required accounts (fee vaults, owner program) properly initialized
This edge case (dlp-owned but closed account) is precisely what the new guard in
process_undelegateis designed to catch.
e25f8c2 to
5c893f7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
tests/test_undelegate_close_account.rs (1)
40-42: Weak assertion: verify the specific error code 41.The test only checks that an error occurred but doesn't verify that the specific error is
DelegateAccountClosed(error code 41). The transaction could fail for other reasons (e.g., invalid account, missing signer), and this test would incorrectly pass. Additionally, the debugprintln!should be removed.🔎 Recommended fix to assert the specific error and remove debug output
let res = banks.process_transaction(tx).await; - println!("{:?}", res); - assert!(res.is_err(), "Delegate account is already closed"); + + let err = res.expect_err("Expected transaction to fail for closed account"); + let transaction_error = err.unwrap(); + match transaction_error { + solana_sdk::transaction::TransactionError::InstructionError(_, instruction_error) => { + match instruction_error { + solana_program::instruction::InstructionError::Custom(code) => { + assert_eq!( + code, 41, + "Expected DelegateAccountClosed error (code 41), got: {}", + code + ); + } + _ => panic!("Expected Custom error, got: {:?}", instruction_error), + } + } + _ => panic!("Expected InstructionError, got: {:?}", transaction_error), + }
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
src/error.rssrc/processor/fast/undelegate.rstests/test_undelegate_close_account.rs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-15T11:45:25.802Z
Learnt from: snawaz
Repo: magicblock-labs/delegation-program PR: 107
File: src/entrypoint.rs:141-144
Timestamp: 2025-10-15T11:45:25.802Z
Learning: In the delegation-program codebase, prefer using `log!` (from pinocchio_log) over `msg!` for error and panic scenarios in the entrypoint code, as per maintainer preference.
Applied to files:
tests/test_undelegate_close_account.rs
🧬 Code graph analysis (1)
tests/test_undelegate_close_account.rs (2)
src/pda.rs (4)
delegation_metadata_pda_from_delegated_account(106-112)delegation_record_pda_from_delegated_account(98-104)fees_vault_pda(149-151)validator_fees_vault_pda_from_validator(153-159)tests/fixtures/accounts.rs (2)
get_delegation_metadata_data(99-105)get_delegation_record_data(54-56)
🔇 Additional comments (3)
src/processor/fast/undelegate.rs (2)
91-95: LGTM! Early guard correctly rejects closed accounts.The check correctly identifies a fully closed account (zero lamports AND empty data) and fails fast before expensive validations. The AND condition is appropriate: accounts with empty data but some lamports are handled by the fast-path at line 166, while this early exit prevents processing accounts that have been garbage-collected.
71-71: Documentation accurately reflects the new early-exit behavior.tests/test_undelegate_close_account.rs (1)
45-138: Test setup is comprehensive and correct.The setup properly configures a closed delegated account (0 lamports, empty data) along with all required PDAs and vaults. This correctly exercises the early-exit path in the undelegate processor.
5c893f7 to
681bf71
Compare
Problem
Solution
Deploy Notes
Closes #82
Summary by CodeRabbit
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.