脅threat model
explicit catalog of what kagura defends against, what it doesn't, and what residual risks operators must accept.
defended against
T1: share inflation
Integer math rounds toward zero on both deposit and withdraw. A depositor cannot mint “extra” shares by structuring deposits; the rounding always favors existing shareholders.
T2: clock regression
kagura-core rejects ticks where now < last_tick_unix_ms. If solana's clock somehow goes backward, the tick errors with ClockRegression rather than producing a negative dt.
T3: tick-frequency manipulation
Per-tick accrual is a function of wall-clock dt, not of tick count. Callingrecord_tick twice quickly produces two ticks with very small elapsed_ms each, summing to the same accrual as one tick with the larger dt. Attackers cannot inflate yield by ticking more.
T4: arithmetic overflow
All multiplications use checked_mul in u128. Final results are checked against u64::MAX before truncation. Overflow returns MathOverflow rather than wrapping.
T5: wrong mint
Deposit/withdraw constraints check user_token_account.mint == vault.usdc_mint and user_share_account.mint == vault.share_mint. A malicious user cannot deposit a different spl token and receive shares.
not defended against
R1: authority key compromise
Vault.authority can change funding rate, pause, set new policy. If that key is stolen, the attacker can:
- set rate to 0 (halts yield)
- set rate to 30000 bps (drains treasury fast)
- pause the vault (halts deposits/withdraws/ticks)
The authority cannot drain principal. User funds are held by the principal pda whose token authority is [b"principal-auth", vault.key()]— controllable only by kagura-vault's own withdraw instruction, which requires the user to burn their shares.
R2: treasury exhaustion
If the treasury runs dry, ticks succeed but accrue zero. The advertised apr becomes false. This is an operational risk, not a smart-contract bug.
R3: rpc censorship
Ticker bot depends on rpc. A faulty/censored rpc that drops tick_funding transactions stops accrual. Solana validators cannot censor by program id under normal conditions; rpc providers in principle could. Mitigation: run multiple rpcs, tip via jito, fall back to direct submit.
R4: clock resolution on solana
Solana's Clock sysvar has 1-second resolution. Multiple sub-second ticks within the same second produce elapsed_ms = 0 and accrue zero. This is by design — the math is correct over wall-clock time regardless of tick frequency, and 1-second granularity is still 3,600× finer than the 1-hour cron used by legacy defi.
invariants checked at all times
shares × vault_balance / total_sharesis the exact redemption price; rounding is always toward the vault.treasury + principalnever exceeds the total usdc that has ever been transferred in.vault.last_tick_unix_msis monotonic.- token accounts are owned by the program-derived authority pdas, not by the vault authority key.