PERMANENT COLLECTIONProtocol Reference

TokenAdminPoker

0xA96a11257890ED1C43C16c098E286e18e45E6258 · view on evm.now · deployed at block 25270161

Retained-admin holder of the $111 token's tokenAdmin role. The token itself sees this contract as its admin, but the contract exposes only four narrow forwards: bind or lock the official pool's per-swap fee extension on the skim hook (bindExtension / lockExtension, owner-gated), tune the hook's referral cap (setHookMaxReferralBps), and tune the token's venue-scoped buy-tax rate (setTokenTaxBps). Every other token-admin surface (metadata, image, admin transfer on the token) has no passthrough here and is therefore unreachable, making the rest of the token effectively immutable.

A one-shot setup pins the token address and the canonical pool key. The extension and cap setters take no target arguments; they can only ever act on that pinned pool's hook and that pinned token. The two rate setters use a two-key gate: callable by either owner (the launch key) or the current ProtocolAdmin admin EOA, so each rate stays tunable until BOTH roles are burned.

Concepts

Why the admin is retained

The pool extension slot on the skim hook is empty at launch. A future synchronous extension dispatcher (Design B) binds through this contract's bindExtension; once the extension is proven in production, lockExtension freezes the binding permanently. Retaining the owner key is what keeps that path open. When the owner is transferred to a dead address, bindExtension, lockExtension, and setup become unreachable, and the two rate setters fall back to the ProtocolAdmin key alone.

The two-key carve-out pattern

setHookMaxReferralBps and setTokenTaxBps accept msg.sender == owner OR msg.sender == adminContract.admin(). Each rate tracks a market regime that shifts over the protocol's lifetime (referral economics, side-pool competition), so it should stay tunable past the 1-year ProtocolAdmin timer and past an owner renouncement. The bounds are enforced downstream, not here:

Setter Enforced by Bound
setHookMaxReferralBps the skim hook [0, 1_000] bps of swap volume, 100k denominator (at most 1% of volume)
setTokenTaxBps the $111 token [0, taxBpsMax], with taxBpsMax <= 2000 structural (never above 20%; launch rate 1500)

Either role being alive keeps the value tunable; both burned freezes it where it last stood.

Reading the wiring

bash
cast call 0xA96a11257890ED1C43C16c098E286e18e45E6258 "owner()(address)" --rpc-url https://ethereum-rpc.publicnode.com
cast call 0xA96a11257890ED1C43C16c098E286e18e45E6258 "token()(address)" --rpc-url https://ethereum-rpc.publicnode.com
cast call 0xA96a11257890ED1C43C16c098E286e18e45E6258 "poolKey()(address,address,uint24,int24,address)" --rpc-url https://ethereum-rpc.publicnode.com

The last component of poolKey is the skim hook, the only contract the extension and referral-cap setters can ever call.

Write functions

setup

solidity
function setup(address _token, PoolKey _poolKey) external

Access: owner-only, one-shot (reverts AlreadySetup on a second call)

Pins the $111 token address and the canonical pool key (including its hook). Reverts ZeroAddress if the token or the key's hook is zero. Pinning here is what lets bindExtension / lockExtension / setHookMaxReferralBps drop their target arguments: they act only on this pool and this token, never on a caller-supplied address.

bindExtension

solidity
function bindExtension(address extension) external

Access: owner-only (reverts NotOwner otherwise; reverts NotSetup before setup)

Binds (or re-binds, or swaps) the per-swap fee extension on the pinned pool's hook by forwarding setPoolExtension(poolKey, extension, ""). Works because this contract holds the token-admin role; the hook additionally requires the extension to be allowlisted on its side. Re-callable until lockExtension freezes the binding. Emits ExtensionBound.

lockExtension

solidity
function lockExtension() external

Access: owner-only (reverts NotOwner otherwise; reverts NotSetup before setup)

One-way freeze of the pool's extension binding, forwarding lockPoolExtension(poolKey) to the hook. Intended for after a bound extension has proven itself in production; once called, the binding can never change again. Emits ExtensionLocked.

setHookMaxReferralBps

solidity
function setHookMaxReferralBps(uint24 newCap) external

Access: two-key (either owner or the current ProtocolAdmin.admin() EOA; all other callers revert NotAuthorized; reverts NotSetup before setup)

Updates the referral cap on the skim hook for the pinned pool by forwarding setMaxReferralBpsOfVolume(poolKey, newCap). The hook enforces the hard upper bound of 1_000 (1% of swap volume in the 100k denominator); this wrapper just forwards the value. Launch value is 250 (0.25% of volume). Because the gate accepts the ProtocolAdmin admin as well as the owner, the cap survives the 1-year admin timer and an owner renouncement; it freezes only when both roles are burned. Emits MaxReferralBpsSet.

setTokenTaxBps

solidity
function setTokenTaxBps(uint16 newBps) external

Access: two-key (either owner or the current ProtocolAdmin.admin() EOA; all other callers revert NotAuthorized; reverts NotSetup if the token isn't pinned yet)

Updates the $111 token's venue-scoped buy-tax rate by forwarding setTaxBps(newBps) to the token. The token enforces the bound (newBps <= taxBpsMax, itself capped at a structural 2000, so the rate can never exceed 20%; the launch rate is 1500). The token reverts TaxNotEnabled if its tax feature is off, so the forward is safe against a dormant token. Same two-key survival semantics as setHookMaxReferralBps. Emits TokenTaxBpsSet.

transferOwnership

solidity
function transferOwnership(address newOwner) external

Access: owner-only (reverts NotOwner otherwise)

Transfers the retained owner key. Reverts ZeroAddress for address(0); to effectively renounce, transfer to a dead-but-non-zero address, which makes the owner-only functions unreachable while leaving the two-key rate setters alive through the ProtocolAdmin path. Emits OwnershipTransferred.

Read functions

adminContract

solidity
function adminContract() external view returns (ProtocolAdmin)

The immutable ProtocolAdmin reference used by the two-key gates. Its current admin() is accepted alongside owner in setHookMaxReferralBps and setTokenTaxBps.

owner

solidity
function owner() external view returns (address)

The protocol's launch key (or its successor via transferOwnership). Gates setup, bindExtension, lockExtension, and transferOwnership, and is one of the two accepted keys on the rate setters.

poolKey

solidity
function poolKey() external view returns (Currency currency0, Currency currency1, uint24 fee, int24 tickSpacing, IHooks hooks)

The canonical pool key pinned by setup: currency pair, LP fee, tick spacing, and the hook address. The hook component is the only contract bindExtension / lockExtension / setHookMaxReferralBps can ever call.

setupDone

solidity
function setupDone() external view returns (bool)

True once setup has run. While false, every forward reverts NotSetup (the tax setter checks the pinned token instead, with the same effect).

token

solidity
function token() external view returns (address)

The $111 token address pinned by setup, target of setTokenTaxBps. address(0) until setup.

Events

ExtensionBound

solidity
event ExtensionBound(address indexed hook, address indexed extension)

Emitted on every bindExtension with the hook (indexed) and the extension (indexed). A rebind emits again with the new extension; address(0) means the slot was cleared.

ExtensionLocked

solidity
event ExtensionLocked(address indexed hook)

Emitted once, on lockExtension, with the hook (indexed). From this point the pool's extension binding is permanent.

MaxReferralBpsSet

solidity
event MaxReferralBpsSet(address indexed hook, uint24 newCap)

Emitted on every setHookMaxReferralBps with the hook (indexed) and the new cap. The latest event carries the live referral ceiling for attributed swaps.

OwnershipTransferred

solidity
event OwnershipTransferred(address indexed from, address indexed to)

Emitted at construction (from address(0)) and on every transferOwnership. Tracks who holds the retained owner key.

TokenTaxBpsSet

solidity
event TokenTaxBpsSet(address indexed token, uint16 newBps)

Emitted on every setTokenTaxBps with the token (indexed) and the new rate in bps. The latest event carries the live venue-scoped buy-tax rate.

Errors

AlreadySetup()

setup was called a second time. The token and pool pin once and never change.

NotAuthorized()

A rate setter (setHookMaxReferralBps / setTokenTaxBps) was called by an address that is neither owner nor the current ProtocolAdmin.admin().

NotOwner()

An owner-only function (setup, bindExtension, lockExtension, transferOwnership) was called by an address other than owner.

NotSetup()

A forward was attempted before setup pinned its target: the extension and referral-cap setters check setupDone, the tax setter checks the pinned token.

ZeroAddress()

Raised by the constructor for a zero owner or admin-contract address, by setup for a zero token or hook, and by transferOwnership for a zero new owner.

TokenAdminPoker · Permanent Collection