経済 · economics

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:

bash
IL(r) = 2 * sqrt(r) / (1 + r) - 1

For an unbounded position, r can drift arbitrarily, so the IL is unbounded. For a bloom of duration D slots, the realised IL is:

bash
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

StrategyMean ILP95 ILNotes
Uniswap V2 full-range LP12.4%34.2%SOL/USDC, 1-day window
HANAMI 1-day bloom3.3%9.8%Same window, auto-settled
HANAMI 7-day bloom6.1%17.4%Wider tail, still bounded

Chirigiwa penalty redistribution

bash
withdraw_a = (share_a - 0.05 * share_a) + fees_earned_a
withdraw_b = (share_b - 0.05 * share_b) + fees_earned_b

The 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:

rust
pool.cumulative_fee_per_share_a +=
    (fee_amount << 64) / pool.total_liquidity;

A bloom's earned fee on exit is then:

rust
let fees_earned =
    ((pool.cumulative_fee_per_share_a - bloom.entry_cumulative_fee_a) * bloom.liquidity) >> 64;
edit on github ↗