Contract interfaces
All contracts are Solidity 0.8.26, non-upgradeable, and verified on the Elysium explorer. Addresses are in
deployments/<chainId>.json.
| Contract | Role |
|---|---|
PropHook | Uniswap v4 hook (custom curve) holding the quote book, maker inventory, protocol fee and guardian controls. One instance serves every pool. |
PropFactory | Deploys the hook at a mined CREATE2 address and creates pools permissionlessly within global bounds. |
NoReferenceAdapter, SignedReferenceAdapter, HyperCorePrecompileAdapter | Implementations of IReferencePriceAdapter for the per-pool price guardrail. |
SimpleRouter | A minimal third-party-style router: exact-in and exact-out single-pool swaps with native HYPE support. |
Uniswap v4 PoolManager, V4Quoter, StateView, UniversalRouter, Permit2 | Standard Uniswap contracts, resolved per chain (official deployment if verified, otherwise our deployment of the pinned commits). |
PropHook: makers
function registerMaker() external;
function setOperator(address operator, bool allowed) external; // owner only
function setMakerPaused(address maker, bool paused) external; // owner; operators may only pause
function deposit(PoolId poolId, Currency currency, uint256 amount) external payable; // owner only
function withdraw(PoolId poolId, Currency currency, uint256 amount, address to) external; // owner only, never blocked
function updateQuotes(bytes calldata packed) external; // writes msg.sender's quote slots
function updateQuotesPacked344079() external; // same, calldata = 0x0000763e ‖ packed (cheapest)
updateQuotes writes into the caller's own namespace. A maker's quotes are read from its active quoter
(the most recently added operator, or the owner), so an unauthorized caller only ever writes slots that
no maker reads.
PropHook: views
function quoteExactIn(PoolKey calldata key, bool zeroForOne, uint256 amountIn)
external view returns (uint256 amountOut, address maker);
function quoteExactOut(PoolKey calldata key, bool zeroForOne, uint256 amountOut)
external view returns (uint256 amountIn, address maker);
function quoteOf(address maker, PoolId poolId) external view returns (uint256 slot);
function makerInfo(address maker) external view returns (bool registered, bool paused, address quoter);
function inventoryOf(address maker, PoolId poolId) external view returns (uint128 balance0, uint128 balance1);
function poolInfo(PoolId poolId) external view returns (PoolConfig memory);
function poolMakers(PoolId poolId) external view returns (address[] memory);
function currentL2Block() external view returns (uint256);
quoteExactIn and quoteExactOut run the same code path as the swap and return the same numbers to the
wei, in the same block. The official V4Quoter returns identical amounts (tested in the fork suite).
PropHook: events
event MakerRegistered(address indexed maker);
event OperatorSet(address indexed maker, address indexed operator, bool allowed);
event QuoterSet(address indexed maker, address indexed quoter);
event MakerPaused(address indexed maker, bool paused, address indexed by);
event Deposited(PoolId indexed poolId, address indexed maker, Currency currency, uint256 amount);
event Withdrawn(PoolId indexed poolId, address indexed maker, Currency currency, uint256 amount, address to);
event QuoteUpdated(address indexed quoter); // log data = raw packed batch, 34 bytes per pool
event Filled(PoolId indexed poolId, address indexed maker, bool zeroForOne, uint256 amountIn,
uint256 amountOut, uint256 effectivePrice, uint16 quoteSeq, uint32 l2Block);
event FeeAccrued(PoolId indexed poolId, Currency indexed currency, uint256 amount);
event FeesCollected(Currency indexed currency, address indexed to, uint256 amount);
event PoolRegistered(PoolId indexed poolId, uint16 idx, Currency currency0, Currency currency1);
event PoolPaused(PoolId indexed poolId, bool paused);
event GlobalPaused(bool paused);
event PoolAdapterSet(PoolId indexed poolId, address adapter, uint16 maxDeviationBps);
event PoolCapsSet(PoolId indexed poolId, uint128 makerCap0, uint128 makerCap1, uint128 poolCap0, uint128 poolCap1);
event ProtocolFeeSet(uint16 feeBps);
event TreasurySet(address treasury);
event GuardianSet(address guardian);
Filled.amountIn is gross of the protocol fee; effectivePrice is the WAD price used (bid or ask).
PropHook: errors
error NotPoolManager(); error NotFactory(); error NotMaker(); error NotOwnerOrOperator();
error AlreadyRegistered(); error OperatorTaken(); error UnknownPool(); error UnsupportedCurrency();
error PoolIsPaused(); error LiquidityDisabled(); error AmountTooLarge();
error NoEligibleQuote(); error Expired(); error Stale(); error MakerIsPaused();
error CapExceeded(); error InsufficientInventory(); error SpreadTooWide(); error Deviation();
error InventoryCapExceeded(); error InsufficientBalance(); error OutOfBounds(); error NotGuardian();
PropHook: admin
// owner (Ownable2Step)
function setGuardian(address guardian) external;
function setProtocolFee(uint16 feeBps) external; // ≤ 10 bp
function setTreasury(address treasury) external;
function collectFees(Currency currency) external returns (uint256); // to the treasury
// guardian: pause and bounded parameters, never maker funds
function setGlobalPaused(bool paused) external;
function setPoolPaused(PoolId poolId, bool paused) external;
function setPoolAdapter(PoolId poolId, address adapter, uint16 maxDeviationBps) external; // 10..2000 bp
function setPoolCaps(PoolId poolId, uint128 makerCap0, uint128 makerCap1, uint128 poolCap0, uint128 poolCap1) external;
PropFactory
function deployHook(bytes32 salt) external returns (address hook); // once; salt mined off-chain
function createPool(Currency currency0, Currency currency1, PoolParams calldata params)
external returns (PoolKey memory key, PoolId poolId);
event PoolCreated(PoolId indexed poolId, Currency indexed currency0, Currency indexed currency1, address creator);
Pools use LP fee 0 and tick spacing 1 (both irrelevant: the hook prices every swap) and an initial
sqrtPriceX96 of 2^96. Adding liquidity reverts with LiquidityDisabled.
IReferencePriceAdapter
interface IReferencePriceAdapter {
/// price: WAD raw price (same unit as a quote's mid); stamp: L2 block or HyperCore block.
function getReference(PoolId poolId) external view returns (uint256 price, uint256 stamp, bool ok);
}
NoReferenceAdapter always returns ok = false (guardrail skipped). SignedReferenceAdapter accepts
prices pushed by allow-listed keepers and rejects stale ones. HyperCorePrecompileAdapter is compiled
against an isolated interface for Kinetiq's HyperCore market-data precompile, which ships about four
weeks after mainnet; it enforces a maximum HyperCore-block age.