Skip to content

Tests: Address Lookup Table fee-payer drain property coverageΒ #641

Closed

Description

@dev-jodee

What would you like?

Add Address Lookup Table roles to the fee-payer drain property test, so the ALT policy matrix is machine-checked rather than relying on hand-written one-flag-at-a-time cases.

Background. The [validation.fee_payer_policy.*] flags in kora.toml decide when the fee payer (the paymaster's own key, which signs every transaction) may appear in a privileged slot of an instruction. Every flag defaults to false. The invariant under test:

The fee payer is gated in a given role exactly when that role's flag is off, and a non-fee-payer is never gated.

The harness already exists. Add one file:

crates/lib/src/validator/transaction_validator/fee_payer_policy_props/alt.rs

implementing the DrainRole trait, and declare it with mod alt; in that directory's mod.rs. system.rs in the same directory is the reference implementation: copy its shape, including the proptest! block at the bottom.

impl DrainRole for AltRole {
    const ROLES: &'static [Self] = &[/* one variant per gated account slot */];
    fn allowed_programs() -> Vec<String> { /* ALT program id */ }
    fn flag(self, policy: &mut FeePayerPolicy) -> &mut bool { /* &mut policy.alt.* */ }
    fn instruction(self, actor: &Pubkey) -> Instruction { /* put `actor` in the gated slot */ }
}

Flags to cover (5): allow_create, allow_extend, allow_freeze, allow_deactivate, allow_close.

Which slot the validator gates (see validate_fee_payer_usage in crates/lib/src/validator/transaction_validator.rs):

Instruction Gated slots
CreateLookupTable authority or payer
ExtendLookupTable authority or payer (payer is optional)
FreezeLookupTable authority
DeactivateLookupTable authority
CloseLookupTable authority

Where a flag gates more than one slot, add one role variant per slot. system.rs does this with CreateAccountPayer / CreateAccountNewAccount, both mapping to the same flag.

Acceptance criteria

  • Every flag above has at least one role, and the two-slot flags have one role per slot.
  • cargo test -p kora-lib --lib fee_payer_policy_props passes.
  • just check is clean.
  • Mutation proof in the PR description. Point one role's flag() at a different policy field, show the property failing, then revert. A property test that cannot fail is worse than no test, and this is the one thing review cannot easily verify by reading.

Notes

  • Instruction builders live in solana_address_lookup_table_interface, already used by the unit tests in transaction_validator.rs. create_lookup_table returns the instruction alongside the derived table address.
  • ALT has no unconditional drainage guard, so every case reaches the flag gate. (Some other program types do have one, which is why their issues carry extra warnings.)
  • If your property fails against current code, that is a possible fee-payer drain gap, not a PR. Do not post the reproducer, the failing seed, or the proptest-regressions file. Report it privately via the advisory link in SECURITY.md.
  • Comment to claim. One program type per contributor, please, so the files stay independent.

Area

Transaction handling

Activity

  1. linear commented on Aug 20, 2026

    @linear
  2. RlxChap2 commented on Aug 22, 2026

    @RlxChap2
    Contributor

    Claiming this issue. I’ve implemented the ALT role coverage, including the two-slot Create and Extend cases, and verified the requested mutation proof. I’ll open the PR shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions