Skip to main content

BunniHook

BunniHook is a Uniswap v4 hook responsible for handling swaps on Bunni. It implements auto-rebalancing executed via FloodPlain and uses am-AMM to recapture LVR & MEV.

Structs and Enums

BoolOverride

enum BoolOverride {
UNSET,
TRUE,
FALSE
}

ObservationState

struct ObservationState {
uint32 index;
uint32 cardinality;
uint32 cardinalityNext;
Oracle.Observation intermediateObservation;
}

RebalanceOrderHookArgs

struct RebalanceOrderHookArgs {
PoolKey key;
RebalanceOrderPreHookArgs preHookArgs;
RebalanceOrderPostHookArgs postHookArgs;
}

RebalanceOrderPreHookArgs

struct RebalanceOrderPreHookArgs {
Currency currency;
uint256 amount;
}

RebalanceOrderPostHookArgs

struct RebalanceOrderPostHookArgs {
Currency currency;
}

Functions

getObservation

function getObservation(
PoolKey calldata key,
uint256 index
) external view returns (Oracle.Observation memory observation)

Returns the observation for the given pool key and observation index.

Parameters:

NameTypeDescription
keystruct PoolKeyThe pool key
indexuint256The observation index

Return Value:

NameTypeDescription
observationOracle.ObservationThe observation struct

getState

function getState(
PoolKey calldata key
) external view returns (ObservationState memory state)

Returns the TWAP oracle observation state for the given pool key.

Parameters:

NameTypeDescription
keystruct PoolKeyThe pool key

Return Value:

NameTypeDescription
stateObservationStateThe state struct

observe

function observe(
PoolKey calldata key,
uint32[] calldata secondsAgos
) external view returns (int56[] memory tickCumulatives)

Observe the given pool for the timestamps.

Parameters:

NameTypeDescription
keystruct PoolKeyThe pool key
secondsAgosuint32[]The timestamps to observe

Return Value:

NameTypeDescription
tickCumulativesint56[]The tick cumulatives for the given timestamps

isValidParams

function isValidParams(
bytes calldata hookParams
) external view returns (bool)

Validates if the given hook params are valid.

Parameters:

NameTypeDescription
hookParamsbytesThe hook params

Return Value:

NameTypeDescription
isValidboolTrue if the hook params are valid

ldfStates

function ldfStates(
PoolId id
) external view returns (bytes32)

The LDF state of a given pool. Used for evaluating the LDF.

Parameters:

NameTypeDescription
idPoolIdThe pool id

Return Value:

TypeDescription
bytes32The LDF state

slot0s

function slot0s(
PoolId id
) external view returns (
uint160 sqrtPriceX96,
int24 tick,
uint32 lastSwapTimestamp,
uint32 lastSurgeTimestamp
)

The slot0 state of a given pool.

Parameters:

NameTypeDescription
idPoolIdThe pool id

Return Values:

NameTypeDescription
sqrtPriceX96uint160The square root price
tickint24The tick of the pool
lastSwapTimestampuint32The timestamp of the last swap
lastSurgeTimestampuint32The timestamp of the last surge

vaultSharePricesAtLastSwap

function vaultSharePricesAtLastSwap(
PoolId id
) external view returns (
bool initialized,
uint120 sharePrice0,
uint120 sharePrice1
)

The share prices of the vaults used by the pool at the last swap.

Parameters:

NameTypeDescription
idPoolIdThe pool id

Return Values:

NameTypeDescription
initializedboolTrue if the share prices have been initialized
sharePrice0uint120The underlying assets each share of vault0 represents, scaled by 1e18
sharePrice1uint120The underlying assets each share of vault1 represents, scaled by 1e18

getAmAmmEnabled

function getAmAmmEnabled(
PoolId id
) external view returns (bool)

Returns whether am-AMM is enabled for the given pool.

Parameters:

NameTypeDescription
idPoolIdThe pool id

Return Value:

TypeDescription
boolTrue if am-AMM is enabled for the pool

increaseCardinalityNext

function increaseCardinalityNext(
PoolKey calldata key,
uint32 cardinalityNext
) external returns (
uint32 cardinalityNextOld,
uint32 cardinalityNextNew
)

Increase the cardinality target for the given pool.

Parameters:

NameTypeDescription
keystruct PoolKeyThe pool key
cardinalityNextuint32The new cardinality target

Return Values:

NameTypeDescription
cardinalityNextOlduint32The old cardinality target
cardinalityNextNewuint32The new cardinality target

updateLdfState

function updateLdfState(
PoolId id,
bytes32 newState
) external

Update the LDF state of the given pool. Only callable by BunniHub.

Parameters:

NameTypeDescription
idPoolIdThe pool id
newStatebytes32The new LDF state

claimProtocolFees

function claimProtocolFees(
Currency[] calldata currencyList,
address recipient
) external

Claim protocol fees for the given currency list. Only callable by the owner.

Parameters:

NameTypeDescription
currencyListCurrency[]The list of currencies to claim fees for
recipientaddressThe recipient of the fees

setZone

function setZone(
IZone zone
) external

Set the FloodZone contract address. Only callable by the owner.

Parameters:

NameTypeDescription
zoneIZoneThe new FloodZone contract address

setModifiers

function setModifiers(
uint32 newHookFeeModifier,
uint32 newReferralRewardModifier
) external

Set the hook fee & referral reward params. Only callable by the owner.

Parameters:

NameTypeDescription
newHookFeeModifieruint32The new hook fee modifier. 6 decimals.
newReferralRewardModifieruint32The new referral reward modifier. 6 decimals.

setAmAmmEnabledOverride

function setAmAmmEnabledOverride(
PoolId id,
BoolOverride boolOverride
) external

Overrides amAmmEnabled for the given pool. Only callable by the owner.

Parameters:

NameTypeDescription
idPoolIdThe pool id
boolOverrideBoolOverrideThe new override value

setGlobalAmAmmEnabledOverride

function setGlobalAmAmmEnabledOverride(
BoolOverride boolOverride
) external

Overrides amAmmEnabled for all pools. Only callable by the owner.

Parameters:

NameTypeDescription
boolOverrideBoolOverrideThe new override value

rebalanceOrderPreHook

function rebalanceOrderPreHook(
RebalanceOrderHookArgs calldata hookArgs
) external

Called by the FloodPlain contract prior to executing a rebalance order. Should ensure the hook has exactly hookArgs.preHookArgs.amount tokens of hookArgs.preHookArgs.currency upon return.

Parameters:

NameTypeDescription
hookArgsRebalanceOrderHookArgsThe rebalance order hook arguments

rebalanceOrderPostHook

function rebalanceOrderPostHook(
RebalanceOrderHookArgs calldata hookArgs
) external

Called by the FloodPlain contract after executing a rebalance order. Should transfer any output tokens from the order to BunniHub and update pool balances.

Parameters:

NameTypeDescription
hookArgsRebalanceOrderHookArgsThe rebalance order hook arguments

Events

Swap

event Swap(
PoolId indexed id,
address indexed sender,
bool zeroForOne,
uint256 inputAmount,
uint256 outputAmount,
uint160 sqrtPriceX96,
int24 tick,
uint24 fee,
uint256 totalLiquidity
)

Emitted for swaps between currency0 and currency1.

Parameters:

NameTypeDescription
idPoolIdThe abi encoded hash of the pool key struct for the pool that was modified
senderaddressThe address that initiated the swap call, and that received the callback
zeroForOneboolTrue if swapping token0 for token1, false otherwise
inputAmountuint256The input token amount
outputAmountuint256The output token amount
sqrtPriceX96uint160The sqrt(price) of the pool after the swap, as a Q64.96
tickint24The log base 1.0001 of the price of the pool after the swap
feeuint24The swap fee rate charged, 6 decimals
totalLiquidityuint256The total virtual liquidity of the pool during and after the swap

SetZone

event SetZone(IZone zone)

Emitted when the FloodZone contract address is set.

Parameters:

NameTypeDescription
zoneIZoneThe new FloodZone contract address

SetModifiers

event SetModifiers(uint32 indexed hookFeeModifier, uint32 indexed referrerRewardModifier)

Emitted when the hook fee and referral reward modifiers are set.

Parameters:

NameTypeDescription
hookFeeModifieruint32The new hook fee modifier
referrerRewardModifieruint32The new referral reward modifier

SetAmAmmEnabledOverride

event SetAmAmmEnabledOverride(PoolId indexed id, BoolOverride indexed boolOverride)

Emitted when the am-AMM enabled override is set for a specific pool.

Parameters:

NameTypeDescription
idPoolIdThe pool id
boolOverrideBoolOverrideThe new override value

SetGlobalAmAmmEnabledOverride

event SetGlobalAmAmmEnabledOverride(BoolOverride indexed boolOverride)

Emitted when the global am-AMM enabled override is set.

Parameters:

NameTypeDescription
boolOverrideBoolOverrideThe new override value

Swap

event Swap(
PoolId indexed id,
address indexed sender,
bool zeroForOne,
uint256 inputAmount,
uint256 outputAmount,
uint160 sqrtPriceX96,
int24 tick,
uint24 fee,
uint256 totalLiquidity
)

Emitted for swaps between currency0 and currency1.

Parameters:

NameTypeDescription
idPoolIdThe abi encoded hash of the pool key struct for the pool that was modified
senderaddressThe address that initiated the swap call, and that received the callback
zeroForOneboolTrue if swapping token0 for token1, false otherwise
inputAmountuint256The input token amount
outputAmountuint256The output token amount
sqrtPriceX96uint160The sqrt(price) of the pool after the swap, as a Q64.96
tickint24The log base 1.0001 of the price of the pool after the swap
feeuint24The swap fee rate charged, 6 decimals
totalLiquidityuint256The total virtual liquidity of the pool during and after the swap

SetZone

event SetZone(IZone zone)

Emitted when the FloodZone contract address is set.

Parameters:

NameTypeDescription
zoneIZoneThe new FloodZone contract address

SetHookFeeModifier

event SetHookFeeModifier(uint88 indexed newModifier)

Emitted when the hook fee modifier is set.

Parameters:

NameTypeDescription
newModifieruint88The new fee modifier

SetAmAmmEnabledOverride

event SetAmAmmEnabledOverride(PoolId indexed id, BoolOverride indexed boolOverride)

Emitted when the am-AMM enabled override is set for a specific pool.

Parameters:

NameTypeDescription
idPoolIdThe pool id
boolOverrideBoolOverrideThe new override value

SetGlobalAmAmmEnabledOverride

event SetGlobalAmAmmEnabledOverride(BoolOverride indexed boolOverride)

Emitted when the global am-AMM enabled override is set.

Parameters:

NameTypeDescription
boolOverrideBoolOverrideThe new override value

Hook Parameters Format

The hookParams for BunniHook are encoded as follows:

| feeMin - 3 bytes | feeMax - 3 bytes | feeQuadraticMultiplier - 3 bytes | feeTwapSecondsAgo - 3 bytes | surgeFee - 3 bytes | surgeFeeHalfLife - 2 bytes | surgeFeeAutostartThreshold - 2 bytes | vaultSurgeThreshold0 - 2 bytes | vaultSurgeThreshold1 - 2 bytes | rebalanceThreshold - 2 bytes | rebalanceMaxSlippage - 2 bytes | rebalanceTwapSecondsAgo - 2 bytes | rebalanceOrderTTL - 2 bytes | amAmmEnabled - 1 byte | oracleMinInterval - 4 bytes |
  • feeMin (3 bytes): A uint24 value representing the minimum swap fee.
  • feeMax (3 bytes): A uint24 value representing the maximum swap fee.
  • feeQuadraticMultiplier (3 bytes): A uint24 value used in the dynamic fee calculation. See Fee Calculation.
  • feeTwapSecondsAgo (3 bytes): A uint24 value representing the time window for the TWAP used in fee calculation. In seconds.
  • surgeFee (3 bytes): A uint24 value representing the surge fee.
  • surgeFeeHalfLife (2 bytes): A uint16 value representing the half-life of the surge fee's exponential decrease. In seconds. Cannot be 0.
  • surgeFeeAutostartThreshold (2 bytes): A uint16 value representing the threshold for auto-starting the surge fee after a swap. In seconds.
  • vaultSurgeThreshold0 (2 bytes): A uint16 value representing the surge threshold for vault 0. 1 / vaultSurgeThreshold0 is the actual threshold used. Cannot be 0.
  • vaultSurgeThreshold1 (2 bytes): A uint16 value representing the surge threshold for vault 1. 1 / vaultSurgeThreshold1 is the actual threshold used. Cannot be 0.
  • rebalanceThreshold (2 bytes): A uint16 value representing the threshold for rebalancing. 1 / rebalanceThreshold is the actual threshold used.
  • rebalanceMaxSlippage (2 bytes): A uint16 value representing the maximum slippage allowed during rebalancing. 5 decimals.
  • rebalanceTwapSecondsAgo (2 bytes): A uint16 value representing the time window for the TWAP used in rebalancing. In seconds.
  • rebalanceOrderTTL (2 bytes): A uint16 value representing the Time-To-Live for rebalance orders. In seconds.
  • amAmmEnabled (1 byte): A bool value (0 or 1) indicating whether am-AMM is enabled.
  • oracleMinInterval (4 bytes): A uint32 value representing the minimum interval for TWAP oracle updates. Cannot be 0.

Important Notes

  1. All fee values (feeMin, feeMax, surgeFee) are represented with 6 decimals (i.e., a value of 1,000,000 represents 100%).
  2. The feeQuadraticMultiplier is used in the dynamic fee calculation when feeMin != feeMax and feeTwapSecondsAgo != 0.
  3. If rebalanceThreshold is 0, rebalancing is disabled, and rebalanceMaxSlippage, rebalanceTwapSecondsAgo, and rebalanceOrderTTL should also be 0.
  4. If rebalanceThreshold is not 0, rebalancing is enabled, and rebalanceMaxSlippage, rebalanceTwapSecondsAgo, and rebalanceOrderTTL should also not be 0.

Example Usage

Here's an example of how to encode the hook parameters:

function encodeHookParams(
uint24 feeMin,
uint24 feeMax,
uint24 feeQuadraticMultiplier,
uint24 feeTwapSecondsAgo,
uint24 surgeFee,
uint16 surgeFeeHalfLife,
uint16 surgeFeeAutostartThreshold,
uint16 vaultSurgeThreshold0,
uint16 vaultSurgeThreshold1,
uint16 rebalanceThreshold,
uint16 rebalanceMaxSlippage,
uint16 rebalanceTwapSecondsAgo,
uint16 rebalanceOrderTTL,
bool amAmmEnabled,
uint32 oracleMinInterval
) pure returns (bytes memory) {
return abi.encodePacked(
feeMin,
feeMax,
feeQuadraticMultiplier,
feeTwapSecondsAgo,
surgeFee,
surgeFeeHalfLife,
surgeFeeAutostartThreshold,
vaultSurgeThreshold0,
vaultSurgeThreshold1,
rebalanceThreshold,
rebalanceMaxSlippage,
rebalanceTwapSecondsAgo,
rebalanceOrderTTL,
amAmmEnabled,
oracleMinInterval
);
}

Remember to ensure that all values are within their appropriate ranges and that the parameters are consistent (e.g., rebalancing parameters are all zero if rebalancing is disabled).