Open the app

HookrNativeMechanicsBlockV2

Read about the module holding the five native mechanics rules, its per-quote claim ledger, and its own per-pool counters.

Deployed at 0xD700492b504ba5A72D7de28dDe11Cd7985a7F1ae, compiled from src/HookrNativeMechanicsBlockV2.sol at source commit 8db7fc940938f811f508ba9cb0c8f2d3f24c9a25. Its source is verified on the explorer; see Verification. ABI: /api/v2-abi/HookrNativeMechanicsBlockV2.

Implements: IHookrModuleV1, IHookrStatefulModuleV1, IUnlockCallback

Stateful lifecycle module holding the five Hookr rules on any quote currency; other modules and profiles extend Hookr's rule set alongside it.

Identity

Two pure getters every contract in the graph carries, so an integrator can confirm what it is holding without a bytecode comparison.

function contractName() external pure returns (string memory);   // "HookrNativeMechanicsBlockV2"
function contractVersion() external pure returns (string memory); // "2.1.0"

Constants

NameTypeValue
MODULE_KEYbytes32keccak256("HOOKR_NATIVE_MECHANICS")
EXCLUSIVE_GROUPbytes32keccak256("HOOKR_NATIVE_MECHANICS")
CONFIG_SCHEMA_HASHbytes32keccak256("HookrNativeMechanicsBlockV2.Config(...)"), listing all twenty fields in order
MODULE_VERSIONuint322
PHASE_MASKuint8all phases
MAX_TOTAL_FEE_PIPSuint24500,000
MAX_PROTOCOL_SHARE_BPSuint165,000
MIN_POT_BUY_WEIuint960.001 ether
MAX_QUOTE_DECIMALSuint25636
MAX_GUARD_BLOCKSuint256100,000
MIN_SQRT_PRICE_LIMITuint1604295128740
MAX_SQRT_PRICE_LIMITuint1601461446703485210103287273052203988822378723970341
DEADaddress0x000000000000000000000000000000000000dEaD
NATIVE_CUT_ATTRIBUTION_KEYbytes32keccak256("HOOKR_NATIVE_BUY_CUT")
AUTO_BURN_ATTRIBUTION_KEYbytes32keccak256("HOOKR_NATIVE_AUTO_BURN")
PROTOCOL_SHARE_ATTRIBUTION_KEYbytes32keccak256("HOOKR_NATIVE_PROTOCOL_SHARE")

The schema string names every field in order, and the admission library pins the same literal, so a config encoded against any other layout or any other field meaning fails closed at admission. protocolShareBps is a share of each add-on in basis points, never a flat rate on the quote leg; an encoder that treats it otherwise produces a config that prices completely differently, which is why the hash of the schema string, not only the byte layout, is part of admission.

Six pure getters expose the same values through IHookrModuleV1 and IHookrStatefulModuleV1, and two of the contracts read them back off the module rather than trusting what a registrar typed: the catalog reads statefulModuleMagic() at registration, and the registry round-trips moduleKey, moduleVersion and configSchemaHash against the module when a stack is created.

function moduleKey() external pure returns (bytes32);            // MODULE_KEY
function moduleVersion() external pure returns (uint32);         // MODULE_VERSION
function configSchemaHash() external pure returns (bytes32);     // CONFIG_SCHEMA_HASH
function phaseMask() external pure returns (uint8);              // PHASE_MASK
function exclusiveGroup() external pure returns (bytes32);       // EXCLUSIVE_GROUP
function statefulModuleMagic() external pure returns (bytes32);  // keccak256("HOOKR_STATEFUL_SWAP_MODULE_V1")

statefulModuleMagic() returns the shared marker the accounting kernel checks before it will drive a module through the stateful callbacks. A module that answers anything else is refused.

State Variables

NameTypeDescription
poolManagerIPoolManagerImmutable. The v4 singleton
stackRegistryIHookrStackRegistryV1Immutable. Source of the frozen stack and config hash
protocolRecipientaddressImmutable. The only address that may receive the protocol share
potWeimapping(bytes32 => uint256)Current pot balance per pool
potBuyCountmapping(bytes32 => uint256)Qualifying buys counted per pool
potLastQualifyingBlockmapping(bytes32 => uint40)Last block the counter advanced
guardBuyBlockmapping(bytes32 => uint40)Block the guard cap is currently counting
guardBuyAmountmapping(bytes32 => uint96)Quote spent on buys in that block
guardLpEarnedQuotemapping(bytes32 => uint256)Cumulative guard-window quote LP earnings, informational
totalHookFeesWeimapping(bytes32 => uint256)Cumulative LP-reward plus pot cuts
totalBurnedTokensmapping(bytes32 => uint256)Cumulative subject burned
totalLpDonatedWeimapping(bytes32 => uint256)Cumulative LP donations
totalPotPaidWeimapping(bytes32 => uint256)Cumulative pot payouts
totalProtocolShareWeimapping(bytes32 => uint256)Cumulative protocol share across every stream
protocolShareByStreammapping(bytes32 => mapping(uint8 => uint256))Cumulative protocol share per pool per ProtocolStream
claimablemapping(address => mapping(address => uint256))Pull-claim ledger, quote then account
totalClaimLiabilitymapping(address => uint256)Backed ERC-6909 liability per quote

Functions

constructor

Pins the PoolManager, the stack registry and the protocol recipient. Reverts ZeroAddress if any is zero, or if the PoolManager or the registry has no code.

constructor(
    IPoolManager poolManager_,
    IHookrStackRegistryV1 stackRegistry_,
    address protocolRecipient_
);

Parameters

NameTypeDescription
poolManager_IPoolManagerThe Uniswap v4 singleton every pool settles through
stackRegistry_IHookrStackRegistryV1The registry holding each pool's frozen stack
protocolRecipient_addressThe treasury forwarder, immutable for the life of the module

validateConfig

Structural validation. Decodes the config, enforces every bound, and returns its hash. It is pure, so it cannot read the recipient immutable; admission must also call validateProtocolShare.

function validateConfig(bytes calldata config) external pure returns (bytes32 configHash);

Parameters

NameTypeDescription
configbytesABI-encoded Config, exactly 640 bytes

Returns

NameTypeDescription
configHashbytes32keccak256 of the config bytes

validateProtocolShare

Admission read proving the config routes a within-ceiling share to this module's own recipient and, for an ERC-20 quote with a pot, a decimals-aware floor. Reverts InvalidConfig for a structurally invalid config; returns false rather than reverting for a valid config that fails either check.

function validateProtocolShare(bytes calldata config) external view returns (bool enforced);

Parameters

NameTypeDescription
configbytesABI-encoded Config

Returns

NameTypeDescription
enforcedboolTrue when the share, the recipient and the pot floor all hold

requiresLockedFoundingPosition

Admission read reporting whether this config asks for a guard window, which is what makes it new-token-lane only.

function requiresLockedFoundingPosition(bytes calldata config) external pure returns (bool required);

Parameters

NameTypeDescription
configbytesABI-encoded Config

Returns

NameTypeDescription
requiredboolTrue when guardEndBlock is non-zero

validateStack

Derives the worst-case deltas this exact config may request, for the registry to check against the catalog registration. Reverts InvalidConfig if the config does not match the pool it is being frozen into, or if the kernel is not a stateful kernel on the same PoolManager.

function validateStack(
    bytes32 poolId,
    address kernel,
    address subject,
    address quote,
    bytes calldata config
) external view returns (HookrModuleTypesV1.ModuleConfigCaps memory caps);

Parameters

NameTypeDescription
poolIdbytes32The pool being created
kerneladdressThe root hook bound to the pool
subjectaddressThe subject token
quoteaddressThe quote currency
configbytesABI-encoded Config

Returns

NameTypeDescription
capsModuleConfigCapsConfig hash plus the surcharge, specified-take, unspecified-take and subject-take ceilings for this pool

beforeAddLiquidity

Blocks any sender other than the config's lockedLiquidityProvider while a guard window is open, and admission requires that field to be the coordinator whenever a guard is set. Reverts ExternalLiquidityBlockedDuringGuard.

function beforeAddLiquidity(
    HookrModuleTypesV1.LiquidityContext calldata context,
    bytes calldata config
) external view returns (bool allowed);

Returns

NameTypeDescription
allowedboolTrue when the add may proceed

beforeSwapStateful

Returns the LP-fee surcharge the kernel adds to the base fee to form the override and, on an exact-input buy, computes the quote-side takes. Enforces the guard cap and the full-fill limit.

function beforeSwapStateful(
    HookrStatefulModuleTypesV1.BeforeSwapContext calldata context,
    bytes calldata config
) external returns (HookrStatefulModuleTypesV1.BeforeSwapResult memory result);

Returns

NameTypeDescription
resultBeforeSwapResultLP-fee surcharge, quote take in pips, in bps and in absolute amount, donation and escrow weights, royalty bps, claim recipient and attribution key

afterSwapStateful

Takes the protocol share on the unspecified quote leg, applies the burn to subject output on an exact-input buy, releases the guard's per-block buy ledger and credits guardLpEarnedQuote. The pot counters advance in beforeSwapStateful, not here.

function afterSwapStateful(
    HookrStatefulModuleTypesV1.AfterSwapContext calldata context,
    bytes calldata config
) external returns (HookrStatefulModuleTypesV1.AfterSwapResult memory result);

Returns

NameTypeDescription
resultAfterSwapResultQuote take and subject take with their recipients and attribution keys

beforeSwap

Reverts StatefulKernelRequired. A read-only kernel must never execute this module as if it were stateless.

function beforeSwap(
    HookrModuleTypesV1.SwapContext calldata,
    bytes calldata
) external pure returns (HookrModuleTypesV1.ModuleResult memory);

afterSwap

Reverts StatefulKernelRequired, for the same reason.

function afterSwap(
    HookrModuleTypesV1.AfterSwapContext calldata,
    bytes calldata
) external pure returns (HookrModuleTypesV1.ModuleResult memory);

claim

Pays the caller everything owed to it in one quote currency. Reverts NothingToClaim when the balance is zero and ClaimTransferFailed when the recipient's measured balance does not rise by exactly the debited amount.

function claim(address quote) external;

Parameters

NameTypeDescription
quoteaddressQuote currency of the accrual; address(0) is native

claimTo

Pays the caller's balance to a different address. Reverts ZeroAddress for a zero recipient.

function claimTo(address quote, address to) external;

Parameters

NameTypeDescription
quoteaddressQuote currency of the accrual
toaddressRecipient of the payment

claimBalance

The module's own ERC-6909 balance held on the PoolManager for one quote currency.

function claimBalance(address quote) public view returns (uint256);

Returns

NameTypeDescription
<none>uint256Balance of the currency id derived from quote

accountingInvariant

Per-quote solvency check. Every quote currency is backed independently.

function accountingInvariant(address quote) external view returns (bool);

Returns

NameTypeDescription
<none>boolTrue when claimBalance(quote) >= totalClaimLiability[quote]

unlockCallback

PoolManager unlock callback used only by claim and claimTo. Burns the module's ERC-6909 balance, takes the currency to the recipient, and returns the measured delta. Reverts NotPoolManager for any other caller and HookNotCalled for an unrecognised action.

function unlockCallback(bytes calldata data) external returns (bytes memory);

Events

HookFeesAccrued

Emitted once per exact-input buy that takes an LP-reward or pot cut

event HookFeesAccrued(
    bytes32 indexed poolId,
    uint256 burnWei,
    uint256 lpWei,
    uint256 potWeiAdded,
    uint256 royaltyWei,
    address royaltyTo
);

Parameters

NameTypeDescription
poolIdbytes32Pool that took the cut
burnWeiuint256Always zero; the burn is reported by AutoBurn
lpWeiuint256Quote donated to in-range LPs
potWeiAddeduint256Quote added to the pot
royaltyWeiuint256Quote credited to the royalty recipient
royaltyToaddressRoyalty recipient

ProtocolShareAccrued

Emitted for each stream that credits the protocol share

event ProtocolShareAccrued(bytes32 indexed poolId, ProtocolStream indexed stream, uint256 amount);

Parameters

NameTypeDescription
poolIdbytes32Pool the accrual belongs to
streamProtocolStreamWhich add-on the slice was carved out of
amountuint256Quote credited to the protocol recipient
enum ProtocolStream { Surcharge, Guard, LpReward, Pot, Burn }

Guard is the snipe-tax slice and only ever accrues on an exact-input buy inside a guard window, which is what keeps guard-window revenue separable from post-guard revenue without arithmetic. A deferred slice taken in afterSwap is always pure surge and reports as Surcharge.

JackpotHit

Emitted when a qualifying buy trips the pot counter

event JackpotHit(bytes32 indexed poolId, address indexed winner, uint256 amountWei, uint256 buyCount);

Parameters

NameTypeDescription
poolIdbytes32Pool that paid the pot
winneraddressRecipient carried in the authenticated hookData
amountWeiuint256Quote credited to the winner's claim balance
buyCountuint256Qualifying-buy counter at the payout

AutoBurn

Emitted when subject output is withheld and sent to the dead address

event AutoBurn(bytes32 indexed poolId, uint256 tokensBurned);

LpRewardsDonated

Emitted when quote is donated to in-range liquidity inside a swap

event LpRewardsDonated(bytes32 indexed poolId, uint256 amountWei);

Claimed

Emitted when an account pulls its claim balance

event Claimed(address indexed quote, address indexed account, address indexed to, uint256 amount);

Errors

InvalidConfig

Thrown when a config is malformed or violates any structural bound

error InvalidConfig();

StatefulKernelRequired

Thrown when a read-only kernel calls the stateless callbacks

error StatefulKernelRequired();

NotKernel

Thrown when the caller is not the pool's frozen kernel, or the frozen config hash does not match

error NotKernel();

NotPoolManager

Thrown when unlockCallback is called by anyone but the PoolManager

error NotPoolManager();

InvalidRuntimeContext

Thrown when the runtime pool, subject, quote or recipient does not match the config

error InvalidRuntimeContext();

MaxBuyExceeded

Thrown when a guard-window buy would push this block's total past the cap

error MaxBuyExceeded(uint256 attemptedQuoteAmount, uint256 maxQuoteAmount);

ExactOutputBlockedDuringGuard

Thrown when an exact-output buy is attempted while the guard window is open

error ExactOutputBlockedDuringGuard();

PartialFillUnsupportedWithInputCuts

Thrown when an exact-input buy with input cuts does not use the canonical full-fill price limit, or does not consume its whole input

error PartialFillUnsupportedWithInputCuts();

ExternalLiquidityBlockedDuringGuard

Thrown when a sender other than the coordinator adds liquidity during the guard window

error ExternalLiquidityBlockedDuringGuard();

InvalidPotRecipient

Thrown when a pot-qualifying buy carries a zero recipient

error InvalidPotRecipient();

NothingToClaim

Thrown when claim or claimTo finds a zero balance

error NothingToClaim();

ZeroAddress

Thrown for a zero constructor argument or a zero claim recipient

error ZeroAddress();

ClaimTransferFailed

Thrown when a claim's measured recipient balance delta does not equal the debited amount

error ClaimTransferFailed();

HookNotCalled

Thrown for an unrecognised unlock-callback action

error HookNotCalled();

ProtocolShareNotEnforced

Thrown on every swap and liquidity add when the config's share exceeds the ceiling or names a foreign recipient

error ProtocolShareNotEnforced();