守 · security

Security

The integration suite is the executable specification. The invariants below are tested against a real validator; any change that breaks them must update both the test and the program in the same commit.

Invariants

  1. Single-author math — every reserve, fee accumulator and share calculation uses checked_* arithmetic on u128 intermediates.
  2. Fee isolation — a bloom that enters at slot S cannot collect any fees from swaps that completed at slot < S.
  3. Permissionless settlesettle_bloom afterend_slot succeeds for any caller, but funds always go to the bloom's owner.
  4. Owner-only chirigiwachirigiwa requiresbloom.owner == ctx.accounts.user.key().
  5. No double settlebloom.settled is set on first settle; second call returns AlreadySettled.
  6. Penalty stays in poolchirigiwa reducespool.reserve_* by share_* - penalty_*, leaving the penalty in the vault for remaining LPs.

Account constraints

Every Anchor accounts struct uses explicit constraint = ... clauses for:

rust
#[account(
    mut,
    constraint = vault_a.key() == pool.vault_a @ HanamiError::InvalidVault,
)]
pub vault_a: Box<Account<'info, TokenAccount>>,

#[account(
    mut,
    constraint = user_token_a.mint == pool.token_a_mint @ HanamiError::InvalidMint,
    constraint = user_token_a.owner == user.key() @ HanamiError::Unauthorized,
)]
pub user_token_a: Box<Account<'info, TokenAccount>>,

#[account(
    mut,
    constraint = bloom.owner == user.key() @ HanamiError::Unauthorized,
    constraint = bloom.pool == pool.key() @ HanamiError::PoolMismatch,
)]
pub bloom: Box<Account<'info, BloomPosition>>,

Reporting a vulnerability

edit on github ↗