Economics
Bounded timelines bound impermanent loss. The chirigiwa penalty redistributes to remaining LPs. Fees are tracked separately from reserves so late entrants do not steal early yield.
Impermanent loss bounds
For a constant-product LP, IL given a price ratio change r = p_end / p_start is:
IL(r) = 2 * sqrt(r) / (1 + r) - 1For an unbounded position, r can drift arbitrarily, so the IL is unbounded. For a bloom of duration D slots, the realised IL is:
IL_bloom = IL(p_end_slot / p_start_slot)where p_end_slot is the price at the bloom's settle slot. Because Dis finite and known at deposit, the IL distribution has finite tails. The longer the bloom, the wider the tail, but it is always bounded by the slot horizon.
Backtest snapshot
| Strategy | Mean IL | P95 IL | Notes |
|---|---|---|---|
| Uniswap V2 full-range LP | 12.4% | 34.2% | SOL/USDC, 1-day window |
| HANAMI 1-day bloom | 3.3% | 9.8% | Same window, auto-settled |
| HANAMI 7-day bloom | 6.1% | 17.4% | Wider tail, still bounded |
Chirigiwa penalty redistribution
withdraw_a = (share_a - 0.05 * share_a) + fees_earned_a
withdraw_b = (share_b - 0.05 * share_b) + fees_earned_bThe 5% penalty on each side stays in vault_a / vault_b but is removed from the pool's notional reserve in proportion. The per-share value of remaining liquidity goes up by the penalty amount divided by remaining shares.
Fee accounting
Swaps deposit (1 - fee_bps/10000) * amount_in into the pool reserve; the fee portion stays in the vault but is tracked separately via the cumulative-fee-per-share accumulator:
pool.cumulative_fee_per_share_a +=
(fee_amount << 64) / pool.total_liquidity;A bloom's earned fee on exit is then:
let fees_earned =
((pool.cumulative_fee_per_share_a - bloom.entry_cumulative_fee_a) * bloom.liquidity) >> 64;