// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
/// ---------------------------------------------------------------------------
/// pmav.fun V2 — the curve IS the pool (Uniswap V4 hook architecture)
///
/// QUOTED VARIANT ("v2q") — the RWA quoted curve lane hook per
/// docs/RWA_QUOTED_CURVE_PLAN.md. Derived from the audited PmavHook v2.1
/// (contracts/src/v2/PmavHook.sol, LIVE on Robinhood Chain 4663) with EXACTLY
/// four categories of change, all forced by the quote currency becoming an
/// IMMUTABLE ERC20 (USDG first; stock tokens in Phase 2) instead of native ETH:
///
/// (a) SETTLEMENT: every native-ETH settle/take/mint path operates on the
/// quote ERC20. Buys settle quote through the PoolManager (routers pull
/// the swapper's quote via Permit2/SETTLE_ALL; the pool currency IS the
/// quote token, never CurrencyLibrary.ADDRESS_ZERO). Sells pay quote out
/// through TAKE_ALL. claimCreatorFees / claimRefund / withdrawPlatformFees
/// pay quote via poolManager.take (an ERC20 transfer by the PM). The dev
/// buy inside create() pulls quote from the creator by transferFrom
/// (one-time ERC20 allowance to this hook) and settles it into the PM.
/// No .call{value:} exists anywhere; create() is not payable; there is
/// no receive() — any native ETH sent here reverts.
/// (b) CURRENCY ORDERING: native ETH was always currency0; an ERC20 quote
/// sorts against each coin address dynamically. The hook derives
/// coinIs0 per pool (coin < QUOTE_TOKEN) and EVERY math site honors it:
/// curve pricing, fee capture side, first-hour cap clamp, graduation
/// trigger direction, graduation reshape, quoter views. Both
/// orientations' constants are precomputed in the constructor.
/// (c) UNITS + CURVE CONSTANTS: all raise/fee/premium/ledger amounts are
/// quote units at QUOTE_DECIMALS. The curve's tick range and liquidity
/// are DERIVED IN THE CONSTRUCTOR from (gradRaise, CURVE_SUPPLY) using
/// the exact v1/v2 boundary conditions (derivation below) — the v2
/// literals [176620, 204350] are ETH/18dp specific and are NOT copied.
/// (d) TICKS: the graduated full-range position bounds stay the spacing-
/// aligned full range [-887270, 887270]; the CURVE range is computed
/// via TickMath from the derived prices and the ordering, aligned to
/// tickSpacing 10.
///
/// Everything else is byte-for-byte v2.1 semantics: 1% fee uniform 70/30
/// creator/platform with the odd unit to the creator, anti-snipe decay,
/// block+1, 2% first-hour fill-to-cap + refund waterfall, 90-minute ticker
/// cooldown, in-place graduation, permanent lock, and the v1-named events
/// (CoinCreated / Trade / Graduated / FeeRecipientChanged ...) with UNCHANGED
/// field names — the Trade fields still read ethGross/ethNet and the Pool
/// struct still reads raisedWei for indexer/terminal ABI compatibility, but
/// the VALUES they carry are quote units at QUOTE_DECIMALS.
///
/// CURVE CONSTANT DERIVATION (the same boundary conditions the v2 curve
/// documents in docs/research/V3_RESEARCH_CURVEDESIGN.md §1.3):
///
/// The curve is a constant-product AMM with virtual reserves (x0, y0)
/// (x = quote, y = coin, both in RAW units), selling S = CURVE_SUPPLY
/// tokens for a total raise of R = gradRaise, chosen so that
/// (1) selling exactly S tokens raises exactly R: R = x0*S/(y0-S)
/// (2) the price moves exactly 16x start->graduation (4x in sqrt):
/// (y0/(y0-S)) * ((x0+R)/x0) = 16
/// By constant product (x0+R)/x0 == y0/(y0-S), so (2) gives y0/(y0-S) = 4,
/// hence y0 = (4/3)*S and from (1) x0 = R/3.
/// (v2 sanity: R = 4.275 ETH gives x0 = 1.425 ETH, y0 = 1,066,666,667
/// tokens — exactly the v1 constants the research doc re-derived.)
///
/// Price start (coin per quote, currency1/currency0 with quote = currency0):
/// Pstart = y0/x0 = 4S/R Pgrad = Pstart/16 = S/(4R)
/// sqrtPstartX96 = 2*sqrt(S/R)*2^96 sqrtPgradX96 = sqrtPstartX96/4
/// Both edges are converted to ticks (TickMath.getTickAtSqrtPrice), rounded
/// to the NEAREST tickSpacing-10 multiple — the exact alignment discipline
/// that produced v2's [176620, 204350] from the derived 176619.27/204346.54.
/// The canonical curve constants are then re-read from the ALIGNED ticks
/// (getSqrtPriceAtTick) and L is sized so the position holds exactly
/// CURVE_SUPPLY tokens at the start edge; the token side is therefore exact
/// by construction and the ≤5-tick alignment shifts land in the realized
/// raise (≤ ~5 bps, the same tolerance class as v2's ~4 bps).
///
/// When the coin sorts BELOW the quote (coinIs0), price = quote/coin is the
/// exact reciprocal, so the aligned ticks NEGATE: the curve runs from
/// -tickStart (init, all tokens) UP to -tickGrad (graduation). Both
/// orientations' sqrt prices and liquidity are precomputed as immutables.
///
/// Vendored dependency pins (see contracts/lib/):
/// v4-periphery commit 3779387e5d296f39df543d23524b050f89a62917
/// (last revision carrying src/utils/BaseHook.sol + HookMiner,
/// parent of PR #510 which moved hooks out of the repo)
/// v4-core commit 59d3ecf53afa9264a16bba0e38f4c5d2231f80bc
/// (tag v4.0.0 + 12, the v4-periphery pinned submodule; matches
/// the deployed PoolManager generation on chain 4663)
///
/// HOOK ADDRESS MINING: the low 14 bits of this contract's address MUST equal
/// 0x28CC = BEFORE_INITIALIZE | BEFORE_ADD_LIQUIDITY | BEFORE_SWAP | AFTER_SWAP
/// | BEFORE_SWAP_RETURNS_DELTA | AFTER_SWAP_RETURNS_DELTA
/// = 1<<13 | 1<<11 | 1<<7 | 1<<6 | 1<<3 | 1<<2.
/// Deployment goes through the canonical CREATE2 deployer
/// (0x4e59b44847b379578588920cA78FbF26c0B4956C, live on chain 4663) with a
/// salt found by an in-script first-flag-satisfying scan — see
/// script/DeployV2Q.s.sol, which asserts
/// uint160(address(hook)) & Hooks.ALL_HOOK_MASK == 0x28CC before anything else.
/// The BaseHook constructor additionally runs Hooks.validateHookPermissions.
///
/// V4-CORE SEMANTICS NOTE (verified against the vendored source, differs from
/// parts of docs/research/V4_DESIGN.md): every Hooks library wrapper no-ops
/// when msg.sender == the hook itself ("noSelfCall"). Consequences:
/// - create()'s own initialize/modifyLiquidity/swap calls NEVER re-enter the
/// hook callbacks, so the spec's `_creating`/`_creatingCoin` transient
/// gating is dead code. beforeInitialize instead reverts UNCONDITIONALLY
/// (Flaunch shape): no pool that is not created by create() can ever
/// attach this hook, and create()'s own initialize skips the callback.
/// - the dev buy cannot be metered by beforeSwap/afterSwap; its fee, cap
/// clamp, ledger credit and Trade event are implemented inline in the
/// create() unlock callback with identical arithmetic.
/// - graduation's inner swap/modifyLiquidity never re-trigger callbacks, so
/// no `_inGraduation` transient is needed; `graduated = true` is still set
/// first for idempotence.
///
/// QUOTE ISSUER PAUSE (disclosed product consequence, not a bug): the quote
/// issuer (USDG: Paxos; stocks: Robinhood Europe UAB) can pause its token.
/// A paused quote freezes this lane's trading — buys, sells, dev buys, fee
/// claims and refund claims revert at the token — and nothing in the hook's
/// ledgers or the pool corrupts; everything resumes when the token unpauses.
/// FEE-ON-TRANSFER quote tokens are NOT supported: the dev-buy pull measures
/// the received amount and reverts on any shortfall, and router settlement of
/// a skimming token fails inside the PoolManager (CurrencyNotSettled). USDG
/// is not fee-on-transfer.
/// ---------------------------------------------------------------------------
import {BaseHook} from "v4-periphery/src/utils/BaseHook.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {PoolId} from "@uniswap/v4-core/src/types/PoolId.sol";
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {
BeforeSwapDelta, BeforeSwapDeltaLibrary, toBeforeSwapDelta
} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol";
import {ModifyLiquidityParams, SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol";
import {LPFeeLibrary} from "@uniswap/v4-core/src/libraries/LPFeeLibrary.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {SqrtPriceMath} from "@uniswap/v4-core/src/libraries/SqrtPriceMath.sol";
import {FullMath} from "@uniswap/v4-core/src/libraries/FullMath.sol";
import {FixedPoint96} from "@uniswap/v4-core/src/libraries/FixedPoint96.sol";
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
import {LiquidityAmounts} from "v4-periphery/src/libraries/LiquidityAmounts.sol";
import {IERC20Minimal} from "@uniswap/v4-core/src/interfaces/external/IERC20Minimal.sol";
import {PmavCoin} from "../PmavCoin.sol";
/// v2.2 GENERATION (docs/V22_HOOK_GENERATION_SPEC.md, decisions locked
/// 2026-07-20). Derived from the audited v2q source; every diff is one of:
/// A. name+ticker PAIR cooldown (was ticker only)
/// B. two step CTO: propose + 12h veto window, inactivity floor 36h
/// C. opt in hookData refund beneficiary (pull only; empty = v2q exact)
/// D. completing buy fee clamp (fee charged on USED gross, audit L1)
/// L. PERMANENT 2% wallet cap (was first hour only): net position bought
/// through this pool per tx.origin, forever; sells free capacity;
/// curve buys fill to cap, post graduation over cap buys revert
/// M. per coin anti snipe ON/OFF chosen by the creator at create()
/// I3 DISCLOSURE (audit): the quote is an ISSUER CONTROLLED token. The
/// issuer can pause transfers or blocklist addresses at any time; a paused
/// quote freezes trading on every coin in this lane (curve included) until
/// unpaused, and a blocklisted fee recipient's accrued claims stay frozen
/// until unblocked. Funds are never lost by this hook; the native ETH lane
/// is unaffected by any quote issuer action.
///
/// @title PmavHookQuoted (v2.2) — the pmav.fun quoted-curve launchpad: factory +
/// Uniswap V4 hook + fee bank, curve denominated in an immutable ERC20
/// @notice Launch a coin for just gas. Every coin: 1B fixed supply, no taxes,
/// no owner. Coins trade from transaction one as a Uniswap V4 pool
/// PAIRED WITH THE QUOTE TOKEN (USDG first) on the canonical
/// PoolManager; the bonding curve is a single concentrated position
/// owned by this hook whose range is derived from gradRaise at
/// deployment and reproduces the v1 virtual-reserve curve law. When
/// the curve sells its 800M tokens the coin graduates IN THE SAME
/// POOL: the curve position is removed and the raise + the reserved
/// 200M tokens are minted as a permanently locked full-range position.
/// No migration, no locker contract — this hook simply has no code
/// path that removes the full-range position.
///
/// Fair-launch rules enforced by the pool itself (router-proof):
/// - trading opens the block AFTER creation (only the dev's own
/// launch buy executes in the creation block)
/// - first hour: no wallet (tx.origin) buys more than 2% of supply
/// (20M) cumulatively — over-cap buys FILL TO CAP and auto-refund
/// the surplus in the same transaction; never a failed buy. If
/// the PoolManager's quote float ever cannot cover the instant
/// refund (settle-after router, young deployment), the surplus
/// queues for a one-click claimRefund() and the buy STILL succeeds
/// - decaying anti-snipe premium on buys (split 70/30 like the base)
/// - 1% fee on curve trades, split 70% creator / 30% platform
/// - sells are NEVER capped, taxed extra, or restricted. Ever.
contract PmavHookQuoted is BaseHook, IUnlockCallback {
using StateLibrary for IPoolManager;
// ---------------------------------------------------------------- consts
uint256 public constant TOTAL_SUPPLY = 1_000_000_000e18;
uint256 public constant CURVE_SUPPLY = 800_000_000e18; // sold on the curve
uint256 public constant LP_SUPPLY = 200_000_000e18; // reserved for the full-range position
/// v2.2: the 2% cap is PERMANENT (net tokens bought through this pool
/// per tx.origin, sells free capacity). No time window exists anymore.
uint256 public constant MAX_WALLET = 20_000_000e18; // 2% of supply
uint256 public constant FEE_BPS = 100; // 1% of gross QUOTE per trade
uint256 public constant ANTI_SNIPE_MAX_BPS = 2_500;
uint256 public constant ANTI_SNIPE_MAX_WINDOW = 120;
uint256 public constant CTO_INACTIVITY = 36 hours; // v2.2 (founder 2026-07-20, was 7 days)
uint256 public constant CTO_VETO_DELAY = 12 hours; // v2.2: public notice window, one claim vetoes
/// @notice v2.2: a just-used exact (name, ticker) PAIR cannot be launched
/// again for this long, enforced IN CONSENSUS. The same ticker
/// under a DIFFERENT name is allowed at any time (locked founder
/// decision; anti exact-vamp only). A hard constant, not
/// owner-tunable.
uint256 public constant PAIR_COOLDOWN = 90 minutes;
uint24 public constant GRADUATED_LP_FEE = 10_000; // 1% in pips (< MAX_LP_FEE 1_000_000)
int24 public constant FULL_TICK_LOWER = -887_270;
int24 public constant FULL_TICK_UPPER = 887_270;
int24 public constant TICK_SPACING = 10;
/// gas floor for the completing buy: revert loudly rather than let
/// estimators settle on a path where graduation cannot execute.
/// PROVENANCE (v2q re-measure, INTENTIONAL DIFF vs v2.1's 4_200_000):
/// the QUOTED graduation step measured ~4,476,504 gas on COLD chain-4663
/// mainnet state at fork block 10,090,000 (graduating buy minus a matched
/// 99.5%-of-curve non-graduating buy —
/// ForkGraduationQ.t.sol::test_graduation_step_gas_vs_floor), about 650k
/// above the v2 native measurement of ~3,823,356. Floor = measured cost
/// + ~11% headroom, the same F1 discipline that set v2's constant; the
/// fork test asserts the floor stays above the measured step.
uint256 public constant GRADUATION_GAS = 5_300_000; // v2.2: F1 re-measure 4,604,569 at fork block 15M; 5.0M was only +8.6% (rule: measured +10%)
address internal constant DEAD = 0x000000000000000000000000000000000000dEaD;
// ------------------------------------------------------ quote immutables
/// the immutable quote ERC20 the whole lane is denominated in (USDG for
/// the Phase 1 deployment; per-stock tokens for Phase 2 deployments of
/// this same artifact). Fixed forever at deployment.
address public immutable QUOTE_TOKEN;
/// the quote token's decimals, validated 6..18 (and cross-checked against
/// the token's own decimals() when it exposes one). INFORMATIONAL for
/// indexers/UIs: on-chain math runs entirely in raw units.
uint8 public immutable QUOTE_DECIMALS;
/// the graduation raise in RAW quote units (Phase 1: 38_000e6 = $38k
/// USDG). The curve constants below derive from it; unlike the ETH lane
/// the raise never drifts with ETH price.
uint256 public immutable GRAD_RAISE;
/// ERC6909 claim id of the quote currency on the PoolManager
/// (CurrencyLibrary: id == uint160 of the token address)
uint256 internal immutable QUOTE_ID;
// ---------------------------------------- derived curve constants, per
// ordering. "_Q0" = quote is currency0 (coin address > quote address):
// price = coin/quote, the curve walks DOWN from TICK_UPPER_Q0 to
// TICK_LOWER_Q0 exactly like v2's ETH pools. "_C0" = coin is currency0:
// price = quote/coin, ticks negate, the curve walks UP from -TICK_UPPER_Q0
// to -TICK_LOWER_Q0.
int24 public immutable TICK_LOWER_Q0; // graduation tick (quote = currency0)
int24 public immutable TICK_UPPER_Q0; // curve start / pool init tick (quote = currency0)
/// derived once at deploy from TickMath — bit-exact with the pool's math
uint160 public immutable SQRT_START_Q0; // sqrtPrice at TICK_UPPER_Q0
uint160 public immutable SQRT_GRAD_Q0; // sqrtPrice at TICK_LOWER_Q0
uint160 public immutable SQRT_START_C0; // sqrtPrice at -TICK_UPPER_Q0
uint160 public immutable SQRT_GRAD_C0; // sqrtPrice at -TICK_LOWER_Q0
uint160 internal immutable SQRT_FULL_LOWER;
uint160 internal immutable SQRT_FULL_UPPER;
/// curve position liquidity per ordering: L such that the position holds
/// exactly the 800M curve tokens at the start edge (the token side is
/// currency1 when quote is currency0, currency0 otherwise — the two L
/// values differ only by the helpers' rounding)
uint128 public immutable L_CURVE_Q0;
uint128 public immutable L_CURVE_C0;
// ---------------------------------------------------------------- state
struct Pool {
address coin;
address feeRecipient;
uint64 launchBlock;
uint64 launchTime;
uint16 snipePeakBps; // frozen at create from factory defaults
uint16 snipeWindow; // seconds; frozen at create
bool graduated;
uint128 tokensSold; // informational + invariant cross-check
uint128 raisedWei; // RAW QUOTE UNITS (name kept for ABI/indexer parity)
}
mapping(PoolId => Pool) public pools;
mapping(address => PoolId) public poolOf; // coin => pool id
address[] public allCoins;
/// cumulative first-hour purchases: pool => tx.origin => tokens bought
/// v2.2 BALANCE BASED 2% cap (founder L3, 2026-07-20): NO persistent
/// ledger. The cap is a live snapshot of tx.origin's holding — selling
/// OR transferring tokens away frees the allowance at once. Only
/// transient per-tx state exists (see the cap helpers below).
/// claimable creator fees, keyed by recipient (QUOTE raw units, pull;
/// backed by the hook's ERC6909 quote claims on the PoolManager)
mapping(address => uint256) public creatorFees;
uint256 public platformFees;
/// queued over-cap refunds (QUOTE raw units, pull; backed by the hook's
/// ERC6909 claims like the fee ledgers). Ruling 19.B waterfall branch 2:
/// written ONLY when a settle-after router hits a PoolManager whose quote
/// float cannot cover the instant take() — expected rarely, and only
/// while the lane is young.
mapping(address => uint256) public refunds;
/// CTO rail, ported byte-for-byte from V1 (see Pmav.sol for the doctrine):
/// an ACTIVE dev can never have their fee stream seized; activity =
/// per-coin steward actions + the recipient claiming fees anywhere.
mapping(address => uint256) public lastActivity; // per-coin steward action
mapping(address => uint256) public lastClaim; // per-recipient claim time
/// one-way fee recipient lock (locked coins are CTO-immune)
mapping(address => bool) public feeRecipientLocked;
/// v2.2: last launch timestamp per case-insensitive (name, ticker) PAIR
/// hash (hash of hashes, collision unambiguous). create() reverts while
/// an exact pair is inside its PAIR_COOLDOWN window, in consensus, no
/// matter what frontend (or none) the caller uses.
mapping(bytes32 => uint64) public pairLastLaunch;
/// v2.2 two step CTO: pending proposal per coin (zeroed on execute; a
/// re-propose overwrites). Any dev liveness signal newer than proposedAt
/// cancels the execute — no silent seizure path exists.
struct CtoProposal {
address newRecipient;
uint64 proposedAt;
}
mapping(address => CtoProposal) public ctoProposals;
/// anti-snipe FACTORY DEFAULTS: copied into each pool at create() and
/// frozen there. Owner tuning affects FUTURE launches only, within the
/// hard caps — no function can change a live pool's swap behavior.
uint256 public antiSnipePeakBps = 1_500; // 15%
uint256 public antiSnipeWindow = 30; // seconds
address public owner;
uint256 private _lock = 1;
// -------------------------------------------------------- transient state
/// swap reentrancy lock (risk register #17: EIP-7702 delegated EOA — or a
/// quote token with transfer callbacks — can run code on the refund
/// take() and try to re-enter the pool mid-callback)
bool private transient _swapLock;
/// fee credited / refund taken in beforeSwap, consumed by afterSwap for
/// the Trade event (reset at the top of every beforeSwap)
uint256 private transient _pendingFee;
uint256 private transient _pendingRefund;
// ---------------------------------------------------------------- events
// v1 names AND field names preserved — the indexer consumes these
// unchanged (§14). The eth* fields carry QUOTE RAW UNITS on this variant.
event CoinCreated(
address indexed token,
bytes32 indexed poolId,
address indexed creator,
address feeRecipient,
string name,
string symbol,
string metadata
);
event Trade(
address indexed token,
address indexed trader,
bool isBuy,
uint256 ethGross,
uint256 ethNet,
uint256 tokenAmount,
uint160 sqrtPriceX96,
uint128 tokensSold,
uint128 raisedWei
);
event Graduated(address indexed token, bytes32 indexed poolId, uint256 ethInPool, uint256 tokensInPool);
event FeeRecipientChanged(address indexed token, address indexed oldRecipient, address indexed newRecipient);
event CtoRedirect(address indexed token, address indexed oldRecipient, address indexed newRecipient);
event CtoRedirectProposed(
address indexed token, address indexed oldRecipient, address indexed newRecipient, uint256 executableAt
);
event AntiSnipeOff(address indexed token);
event FeeRecipientLockedEvent(address indexed token, address indexed recipient);
event CreatorFeesClaimed(address indexed recipient, uint256 amount);
event RefundQueued(address indexed token, address indexed to, uint256 amount);
event RefundClaimed(address indexed to, uint256 amount);
event PlatformFeesWithdrawn(address indexed to, uint256 amount);
event PoolFeesCollected(
address indexed token,
address indexed creatorRecipient,
uint256 creatorWei,
uint256 creatorTokens,
uint256 platformWei,
uint256 platformTokens
);
event AntiSnipeChanged(uint256 peakBps, uint256 window);
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
// ------------------------------------------------------------- modifiers
modifier nonReentrant() {
require(_lock == 1, "reentrancy");
_lock = 2;
_;
_lock = 1;
}
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}
constructor(IPoolManager _manager, address _owner, address _quoteToken, uint8 _quoteDecimals, uint256 _gradRaise)
BaseHook(_manager)
{
require(_owner != address(0), "zero addr");
require(_quoteToken != address(0) && _quoteToken.code.length > 0, "quote not a contract");
require(_quoteDecimals >= 6 && _quoteDecimals <= 18, "quote decimals");
require(_gradRaise > 0, "zero raise");
// deploy-time typo guard: when the quote exposes decimals() it must
// agree with the argument. Tolerant staticcall: a quote without a
// decimals() getter (none planned) simply skips the cross-check.
(bool ok, bytes memory ret) = _quoteToken.staticcall(abi.encodeWithSignature("decimals()"));
if (ok && ret.length >= 32) {
require(abi.decode(ret, (uint256)) == _quoteDecimals, "decimals mismatch");
}
owner = _owner;
QUOTE_TOKEN = _quoteToken;
QUOTE_DECIMALS = _quoteDecimals;
GRAD_RAISE = _gradRaise;
QUOTE_ID = uint256(uint160(_quoteToken));
// ---- curve constant derivation (see the header derivation note) ----
// x0 = R/3, y0 = 4S/3 => Pstart = 4S/R, Pgrad = S/(4R) (coin/quote).
// sqrt(S/R)*2^96, computed as sqrt(floor(S*2^96/R)) << 48 — the floor
// before the sqrt and the integer sqrt cost < 1 part in 1e12 across
// the whole supported (decimals, gradRaise) envelope, far inside the
// tick alignment granularity (a tick is 1 part in 1e4).
uint256 sqrtSRX96 = _sqrt(FullMath.mulDiv(CURVE_SUPPLY, FixedPoint96.Q96, _gradRaise)) << 48;
uint256 sqrtStartExact = sqrtSRX96 * 2; // sqrt(4S/R)*2^96 — the curve start (quote = currency0)
uint256 sqrtGradExact = sqrtSRX96 / 2; // sqrt(S/(4R))*2^96 — 16x price, 4x sqrt below start
// both edges must live strictly inside V4's price space AND inside the
// graduated full range (so the graduation reshape always has room)
require(
sqrtGradExact > TickMath.MIN_SQRT_PRICE && sqrtStartExact < TickMath.MAX_SQRT_PRICE,
"raise out of range"
);
int24 tickStart = _alignNearest(TickMath.getTickAtSqrtPrice(uint160(sqrtStartExact)));
int24 tickGrad = _alignNearest(TickMath.getTickAtSqrtPrice(uint160(sqrtGradExact)));
require(tickGrad > FULL_TICK_LOWER && tickStart < FULL_TICK_UPPER, "raise out of range");
require(tickGrad < tickStart, "degenerate curve"); // 16x span: always ~27,730 ticks
TICK_LOWER_Q0 = tickGrad;
TICK_UPPER_Q0 = tickStart;
SQRT_START_Q0 = TickMath.getSqrtPriceAtTick(tickStart);
SQRT_GRAD_Q0 = TickMath.getSqrtPriceAtTick(tickGrad);
// coin-is-currency0 orientation: price is the exact reciprocal, ticks
// negate (negating a multiple of 10 stays aligned)
SQRT_START_C0 = TickMath.getSqrtPriceAtTick(-tickStart);
SQRT_GRAD_C0 = TickMath.getSqrtPriceAtTick(-tickGrad);
SQRT_FULL_LOWER = TickMath.getSqrtPriceAtTick(FULL_TICK_LOWER);
SQRT_FULL_UPPER = TickMath.getSqrtPriceAtTick(FULL_TICK_UPPER);
// L such that the position holds exactly the 800M curve tokens at the
// start edge (pool initializes there: tokens only). Tokens are
// currency1 in the Q0 orientation, currency0 in the C0 orientation.
L_CURVE_Q0 = LiquidityAmounts.getLiquidityForAmount1(SQRT_GRAD_Q0, SQRT_START_Q0, CURVE_SUPPLY);
L_CURVE_C0 = LiquidityAmounts.getLiquidityForAmount0(SQRT_START_C0, SQRT_GRAD_C0, CURVE_SUPPLY);
require(L_CURVE_Q0 > 0 && L_CURVE_C0 > 0, "zero curve liquidity");
}
// ---------------------------------------------------------- hook wiring
function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
return Hooks.Permissions({
beforeInitialize: true, // gate: only create() pools may attach us
afterInitialize: false,
beforeAddLiquidity: true, // gate: only hook liquidity during curve
afterAddLiquidity: false,
beforeRemoveLiquidity: false, // no third-party curve LP exists to gate
afterRemoveLiquidity: false,
beforeSwap: true, // block+1, cap clamp, quote-specified fee
afterSwap: true, // cap ledger, quote-unspecified fee, graduation, Trade
beforeDonate: false,
afterDonate: false,
beforeSwapReturnDelta: true,
afterSwapReturnDelta: true,
afterAddLiquidityReturnDelta: false,
afterRemoveLiquidityReturnDelta: false
});
}
/// Rogue-pool defense: nobody can initialize ANY pool that references this
/// hook. Our own create() initializes via poolManager with the hook itself
/// as msg.sender, which skips this callback entirely (core noSelfCall).
function _beforeInitialize(address, PoolKey calldata, uint160) internal pure override returns (bytes4) {
revert("pmav: pools only via create()");
}
/// During the curve only the hook may add liquidity (third-party liquidity
/// inside the curve range would absorb buys and desync graduation
/// economics). The hook's own adds skip this callback (noSelfCall); after
/// graduation anyone may LP (v1 parity: community LPs on the V3 pool).
function _beforeAddLiquidity(address, PoolKey calldata key, ModifyLiquidityParams calldata, bytes calldata)
internal
view
override
returns (bytes4)
{
require(pools[key.toId()].graduated, "curve phase");
return BaseHook.beforeAddLiquidity.selector;
}
// ------------------------------------------------------------ beforeSwap
function _beforeSwap(address, PoolKey calldata key, SwapParams calldata params, bytes calldata hookData)
internal
override
returns (bytes4, BeforeSwapDelta, uint24)
{
PoolId id = key.toId();
Pool storage p = pools[id];
// graduated: PURE PASSTHROUGH — no caps, no premium, no deltas.
// (graduation's own inner swap never reaches here: noSelfCall.)
if (p.graduated) return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
require(!_swapLock, "reentrancy");
_swapLock = true;
_pendingFee = 0;
_pendingRefund = 0;
// (a) block+1 — the Noxa killer feature, enforced at pool level.
// (the dev buy never reaches this: hook-initiated swaps skip callbacks)
require(block.number > p.launchBlock, "trading opens next block");
// ordering (delta (b) in the header): a buy is quote-in, which is
// zeroForOne when the quote is currency0 and oneForZero otherwise
bool coinIs0 = Currency.unwrap(key.currency0) != QUOTE_TOKEN;
bool isBuy = params.zeroForOne != coinIs0;
// decaying anti-snipe premium: buys only, frozen params, base 1% always
uint256 feeBps = FEE_BPS + (isBuy ? _antiSnipeBps(p) : 0);
// (b) v2.2 PERMANENT 2% cap — FILL TO CAP + AUTO REFUND on the curve,
// never a failed buy. No time window: the cap is forever.
uint256 refund = 0;
if (isBuy) {
uint256 held0 = _capHeld(id, p.coin, tx.origin);
uint256 capLeft = held0 >= MAX_WALLET ? 0 : MAX_WALLET - held0;
require(capLeft > 0, "wallet cap: 2% max");
if (params.amountSpecified < 0) {
// buy exactIn (the universal path): clamp to the quote the cap allows
uint256 maxGross = _maxGrossForCap(id, coinIs0, capLeft, feeBps);
require(maxGross > 0, "wallet cap: 2% max");
uint256 gross = uint256(-params.amountSpecified);
if (gross > maxGross) refund = gross - maxGross;
} else {
// buy exactOut cannot be partially filled (the router TAKEs the
// exact requested output; no refund exists to give)
require(uint256(params.amountSpecified) <= capLeft, "wallet cap: 2% max");
}
}
// (c) quote-denominated fee, taken on the SPECIFIED side when the
// quote is specified (buy exactIn / sell exactOut). Otherwise
// afterSwap takes it.
if (isBuy == (params.amountSpecified < 0)) {
uint256 quoteGross = _abs(params.amountSpecified) - refund;
// v2.2 (audit L1): on a buy exactIn the fee base is bounded by the
// gross the CURVE can actually consume to graduation (per
// orientation maxNet rounded UP, grossed up rounding UP: the fee
// never undercharges and an oversized completing buy pays fee on
// the USED gross). Sell exactOut is untouched (audit L4).
if (isBuy) {
uint256 maxNet = coinIs0
? SqrtPriceMath.getAmount1Delta(_effSqrtP(id, coinIs0), SQRT_GRAD_C0, L_CURVE_C0, true)
: SqrtPriceMath.getAmount0Delta(SQRT_GRAD_Q0, _effSqrtP(id, coinIs0), L_CURVE_Q0, true);
uint256 maxFeeGross = FullMath.mulDivRoundingUp(maxNet, 10_000, 10_000 - feeBps);
if (quoteGross > maxFeeGross) quoteGross = maxFeeGross;
}
uint256 fee = quoteGross * feeBps / 10_000;
if (fee > 0) {
poolManager.mint(address(this), QUOTE_ID, fee); // ERC6909 claim
_credit(p, fee);
}
if (refund > 0) {
// refund waterfall (ruling 19.B). Both branches charge the
// swapper identically through the returned hook delta; the
// buy SUCCEEDS unconditionally, at any PM balance, under
// settle-first AND settle-after routers.
// v2.2 (audit L2): 32 byte hookData naming a nonzero
// beneficiary routes the surplus to refunds[beneficiary],
// PULL ONLY. Garbage hookData is IGNORED, never a revert.
address beneficiary = _refundBeneficiary(hookData);
if (beneficiary != address(0)) {
poolManager.mint(address(this), QUOTE_ID, refund);
refunds[beneficiary] += refund;
emit RefundQueued(p.coin, beneficiary, refund);
} else if (IERC20Minimal(QUOTE_TOKEN).balanceOf(address(poolManager)) >= refund) {
// 1: instant auto-refund, real quote tokens, straight back
// to the signer (the common path once the lane has
// graduated pools holding quote float)
poolManager.take(Currency.wrap(QUOTE_TOKEN), tx.origin, refund);
} else {
// 2: floatless PM under a settle-after router — queue the
// surplus as the hook's own ERC6909 claim (float-free
// bookkeeping, backed by the buyer's own settle moments
// later); pull via claimRefund()
poolManager.mint(address(this), QUOTE_ID, refund);
refunds[tx.origin] += refund;
emit RefundQueued(p.coin, tx.origin, refund);
}
}
_pendingFee = fee;
_pendingRefund = refund;
uint256 hookTake = fee + refund;
if (hookTake > 0) {
return (BaseHook.beforeSwap.selector, toBeforeSwapDelta(int128(uint128(hookTake)), 0), 0);
}
}
return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
}
// ------------------------------------------------------------- afterSwap
/// `delta` is the raw pool swap result from the swapper's perspective
/// (positive = swapper receives), BEFORE hook deltas are charged to the
/// swapper. Order of operations is load-bearing: fee -> cap -> Trade ->
/// graduation.
function _afterSwap(address, PoolKey calldata key, SwapParams calldata params, BalanceDelta delta, bytes calldata hookData)
internal
override
returns (bytes4, int128)
{
PoolId id = key.toId();
Pool storage p = pools[id];
bool coinIs0 = Currency.unwrap(key.currency0) != QUOTE_TOKEN;
if (p.graduated) {
// v2.2: pricing and fees stay PURE PASSTHROUGH, but the PERMANENT
// 2% cap is enforced here forever — and an over cap exactIn buy
// FILLS TO CAP instead of reverting (founder 2026-07-20): the
// excess tokens are charged back through the afterSwap return
// delta (the UNSPECIFIED side of a buy exactIn, either
// orientation), sold back into the pool inside the same unlock
// (noSelfCall), proceeds refunded in QUOTE through the curve's
// exact waterfall. Buy exactOut over cap still reverts; zero
// remaining capacity reverts; sells decrement saturating and
// never revert. Trade ships with the DELIVERED token amount.
// whole graduated branch lives in a helper to keep this frame
// flat (legacy codegen stack room): cap walk, tail unwind, Trade
return (BaseHook.afterSwap.selector, _afterSwapGraduated(key, p, coinIs0, params, delta, hookData));
}
int128 hookDelta = _settleCurveSwap(p, id, coinIs0, params, delta);
// (d) graduation trigger: price-based — the graduation edge is reached
// iff ~all 800M curve tokens are sold. Sells move price AWAY from it.
// Q0 pools walk DOWN to the edge, C0 pools walk UP to it.
if (params.zeroForOne != coinIs0) {
(uint160 sqrtNow,,,) = poolManager.getSlot0(id);
if (coinIs0 ? sqrtNow >= SQRT_GRAD_C0 : sqrtNow <= SQRT_GRAD_Q0) {
require(gasleft() >= GRADUATION_GAS, "graduation buy needs more gas");
_graduate(key, p, id, coinIs0);
}
}
return (BaseHook.afterSwap.selector, hookDelta);
}
/// v2.2 graduated afterSwap: over cap exactIn buys fill to cap (excess
/// clawed via the return delta and unwound + refunded); sells decrement
/// the ledger saturating; the v1-named Trade ships on every swap. Split
/// out of _afterSwap purely for legacy codegen stack room.
function _afterSwapGraduated(
PoolKey calldata key,
Pool storage p,
bool coinIs0,
SwapParams calldata params,
BalanceDelta delta,
bytes calldata hookData
) internal returns (int128 gradHookDelta) {
PoolId id = key.toId();
bool isBuy = params.zeroForOne != coinIs0;
uint256 e = _abs(int256(coinIs0 ? delta.amount1() : delta.amount0()));
uint256 t = _abs(int256(coinIs0 ? delta.amount0() : delta.amount1()));
if (isBuy) {
(t, gradHookDelta) = _gradBuyCap(key, coinIs0, t, params.amountSpecified < 0, hookData);
}
// sells: nothing to record — balanceOf falls, the transient counter
// resets on the buyer's next buy (balance moved)
// gross == net post graduation (hook takes no fee delta); _emitTrade
// folds sqrtPrice + counters, keeping this frame flat
_emitTrade(p, id, isBuy, e, e, t);
}
/// v2.2: the graduated buy side cap walk (split out of _afterSwap for
/// legacy codegen stack room). Returns (tokens DELIVERED, the afterSwap
/// return delta charging the clawed excess). Zero remaining capacity
/// reverts; exactOut over cap reverts; exactIn over cap fills to cap.
function _gradBuyCap(PoolKey calldata key, bool coinIs0, uint256 t, bool exactIn, bytes calldata hookData)
internal
returns (uint256, int128)
{
PoolId id = key.toId();
address coin = pools[id].coin;
uint256 held = _capHeld(id, coin, tx.origin);
require(held < MAX_WALLET, "wallet cap: 2% max");
if (exactIn && held + t > MAX_WALLET) {
uint256 excess = held + t - MAX_WALLET;
_recordCapBuy(id, tx.origin, MAX_WALLET - held); // only the kept fill
_unwindGradExcess(key, coinIs0, excess, hookData);
return (t - excess, int128(uint128(excess)));
}
require(held + t <= MAX_WALLET, "wallet cap: 2% max");
_recordCapBuy(id, tx.origin, t);
return (t, 0);
}
/// v2.2 (founder 2026-07-20): sell the over cap tail of a graduated
/// exactIn buy back into the pool (orientation aware) and refund the
/// QUOTE proceeds through the curve's exact waterfall (beneficiary
/// hookData honored, pull only; else instant push when the PM's quote
/// float covers it, else pull ledger). Dust tails refund nothing.
function _unwindGradExcess(PoolKey calldata key, bool coinIs0, uint256 excess, bytes calldata hookData)
internal
{
address coin = pools[key.toId()].coin;
BalanceDelta sd = poolManager.swap(
key,
SwapParams({
zeroForOne: coinIs0,
amountSpecified: -int256(excess),
sqrtPriceLimitX96: coinIs0 ? TickMath.MIN_SQRT_PRICE + 1 : TickMath.MAX_SQRT_PRICE - 1
}),
""
);
uint256 quoteBack = uint256(uint128(coinIs0 ? sd.amount1() : sd.amount0()));
if (quoteBack == 0) return;
address beneficiary = _refundBeneficiary(hookData);
if (beneficiary != address(0)) {
poolManager.mint(address(this), QUOTE_ID, quoteBack);
refunds[beneficiary] += quoteBack;
emit RefundQueued(coin, beneficiary, quoteBack);
} else if (IERC20Minimal(QUOTE_TOKEN).balanceOf(address(poolManager)) >= quoteBack) {
poolManager.take(Currency.wrap(QUOTE_TOKEN), tx.origin, quoteBack);
} else {
poolManager.mint(address(this), QUOTE_ID, quoteBack);
refunds[tx.origin] += quoteBack;
emit RefundQueued(coin, tx.origin, quoteBack);
}
}
/// fee (quote-unspecified quadrants), first-hour ledger, bookkeeping and
/// the Trade event for a curve-phase swap
function _settleCurveSwap(Pool storage p, PoolId id, bool coinIs0, SwapParams calldata params, BalanceDelta delta)
internal
returns (int128 hookDelta)
{
// what the pool actually moved (completing buys may consume less than
// stated: unconsumed input through empty liquidity is never taken)
uint256 quotePool = _abs(int256(coinIs0 ? delta.amount1() : delta.amount0()));
uint256 tokenAmount = _abs(int256(coinIs0 ? delta.amount0() : delta.amount1()));
bool isBuy = params.zeroForOne != coinIs0;
uint256 fee;
if (isBuy == (params.amountSpecified < 0)) {
fee = _pendingFee; // already credited in beforeSwap
} else {
// (b') quote fee when the quote is the UNSPECIFIED currency
// (buy exactOut / sell exactIn)
uint256 feeBps = FEE_BPS + (isBuy ? _antiSnipeBps(p) : 0);
fee = quotePool * feeBps / 10_000;
if (fee > 0) {
poolManager.mint(address(this), QUOTE_ID, fee);
_credit(p, fee);
hookDelta = int128(uint128(fee)); // taken from swapper's quote side
}
}
// (c) first-hour ledger: record the ACTUAL fill (clamping already
// happened in beforeSwap; the require is a belt-and-braces invariant)
if (isBuy) {
_recordCapBuy(id, tx.origin, tokenAmount);
require(_capHeld(id, p.coin, tx.origin) <= MAX_WALLET, "cap invariant");
}
// sells: nothing to record — balanceOf falls; a sell must never revert
_swapLock = false;
// bookkeeping + parity event (indexer contract, §14). For buys the
// pool quote is the net (fee charged on top, v1 exact); for sells it
// is the gross (fee taken out of it).
if (isBuy) {
p.tokensSold += uint128(tokenAmount);
p.raisedWei += uint128(quotePool);
} else {
// SATURATING (correctness audit F-3, defense-in-depth): these are
// informational counters only — the graduation trigger is
// price-based (pool sqrtPrice vs the graduation edge), never
// counter-based, so flooring at 0 changes no economics. Underflow
// is already unreachable by conservation (a sell can never return
// more tokens/quote to the curve than the curve ever sold), but a
// sell must NEVER revert on an arithmetic underflow: a reverting
// sell is the #1 honeypot signature, and "sells never revert, ever"
// is a hard invariant of our scanner-clean posture. Make it
// structurally guaranteed rather than conservation-guaranteed.
uint128 t = uint128(tokenAmount);
uint128 e = uint128(quotePool);
p.tokensSold = p.tokensSold > t ? p.tokensSold - t : 0;
p.raisedWei = p.raisedWei > e ? p.raisedWei - e : 0;
}
_emitTrade(
p,
id,
isBuy,
isBuy ? quotePool + fee : quotePool,
// saturate: a sell-exactOut demanding more quote than the curve
// holds partially fills; the credited fee can exceed the fill
isBuy ? quotePool : (quotePool > fee ? quotePool - fee : 0),
tokenAmount
);
}
// ------------------------------------------------------------ graduation
/// Runs INSIDE the completing buy's afterSwap, all in one transaction,
/// inside the router's active unlock. Same poolId forever: no migration,
/// no pool switch, no window where the coin is untradeable. The inner
/// swap/modifyLiquidity calls skip all hook callbacks (noSelfCall).
function _graduate(PoolKey calldata key, Pool storage p, PoolId id, bool coinIs0) internal {
p.graduated = true; // set FIRST (idempotence)
uint160 sqrtGrad = coinIs0 ? SQRT_GRAD_C0 : SQRT_GRAD_Q0;
(int24 tickLo, int24 tickHi) = coinIs0
? (-TICK_UPPER_Q0, -TICK_LOWER_Q0)
: (TICK_LOWER_Q0, TICK_UPPER_Q0);
// 1. remove the whole curve position: hook is credited the raise
// (~GRAD_RAISE quote + any donate() dust as fees) and unsold token
// dust
uint256 quoteAvail;
uint256 tokenCredit;
{
(BalanceDelta d,) = poolManager.modifyLiquidity(
key,
ModifyLiquidityParams({
tickLower: tickLo,
tickUpper: tickHi,
liquidityDelta: -int256(uint256(coinIs0 ? L_CURVE_C0 : L_CURVE_Q0)),
salt: 0
}),
""
);
quoteAvail = uint256(uint128(coinIs0 ? d.amount1() : d.amount0()));
tokenCredit = uint256(uint128(coinIs0 ? d.amount0() : d.amount1()));
}
// 2. repair the boundary overshoot: the completing swap may have walked
// price past the graduation edge through empty liquidity. With zero
// pool liquidity a 1-wei-specified swap walks price back to exactly
// the graduation price at zero cost (input is never consumed).
// Q0 pools overshoot BELOW the edge (repair swaps price UP);
// C0 pools overshoot ABOVE it (repair swaps price DOWN).
{
(uint160 sqrtP,,,) = poolManager.getSlot0(id);
if (coinIs0 ? sqrtP > sqrtGrad : sqrtP < sqrtGrad) {
poolManager.swap(
key, SwapParams({zeroForOne: coinIs0, amountSpecified: -1, sqrtPriceLimitX96: sqrtGrad}), ""
);
}
}
// 3. flip the dynamic LP fee: plain 1% forever (hook takes no deltas
// post-graduation; scanners see a vanilla 1% V4 pool)
poolManager.updateDynamicLPFee(key, GRADUATED_LP_FEE);
// 4. mint the permanently locked full-range position: the entire raise
// + the 200M reserve, amounts computed at the graduation price.
// (-1 wei headroom on both sides: modifyLiquidity rounds owed
// amounts UP, the liquidity helpers round L DOWN — the headroom
// guarantees the owed amounts never exceed what the hook holds.)
uint128 lFull;
{
uint128 lQuote = coinIs0
? LiquidityAmounts.getLiquidityForAmount1(SQRT_FULL_LOWER, sqrtGrad, quoteAvail - 1)
: LiquidityAmounts.getLiquidityForAmount0(sqrtGrad, SQRT_FULL_UPPER, quoteAvail - 1);
uint128 lTok = coinIs0
? LiquidityAmounts.getLiquidityForAmount0(sqrtGrad, SQRT_FULL_UPPER, LP_SUPPLY - 1)
: LiquidityAmounts.getLiquidityForAmount1(SQRT_FULL_LOWER, sqrtGrad, LP_SUPPLY - 1);
lFull = lQuote < lTok ? lQuote : lTok;
}
(BalanceDelta md,) = poolManager.modifyLiquidity(
key,
ModifyLiquidityParams({
tickLower: FULL_TICK_LOWER,
tickUpper: FULL_TICK_UPPER,
liquidityDelta: int256(uint256(lFull)),
salt: 0
}),
""
);
uint256 quoteUsed = uint256(uint128(-(coinIs0 ? md.amount1() : md.amount0())));
uint256 tokUsed = uint256(uint128(-(coinIs0 ? md.amount0() : md.amount1())));
// 5. settle the token side from the hook's 200M reserve (ERC20 custody
// since create), netting the removal's token-dust credit
Currency coinCur = coinIs0 ? key.currency0 : key.currency1;
if (tokUsed > tokenCredit) {
poolManager.sync(coinCur);
require(PmavCoin(p.coin).transfer(address(poolManager), tokUsed - tokenCredit), "transfer");
poolManager.settle();
} else if (tokenCredit > tokUsed) {
// (only reachable via absurd token donations) burn the surplus
poolManager.take(coinCur, DEAD, tokenCredit - tokUsed);
}
// 6. dust sweep, v1 parity: leftover quote units -> platformFees (as
// ERC6909 claims, which also zeroes the hook's remaining positive
// delta); leftover coin dust -> dead address
uint256 quoteDust = quoteAvail - quoteUsed;
if (quoteDust > 0) {
poolManager.mint(address(this), QUOTE_ID, quoteDust);
platformFees += quoteDust;
}
uint256 coinDust = PmavCoin(p.coin).balanceOf(address(this));
if (coinDust > 0) PmavCoin(p.coin).transfer(DEAD, coinDust);
emit Graduated(p.coin, PoolId.unwrap(id), quoteUsed, tokUsed);
}
// ---------------------------------------------------------------- launch
/// @notice Launch a coin. Costs nothing beyond gas; `quoteIn` (optional)
/// is the dev buy in RAW QUOTE UNITS, pulled from the caller by
/// transferFrom (approve this hook first) and executed as the
/// first purchase in the same transaction (candle #1 on every
/// terminal), subject to the same 2% first-hour cap and anti-snipe
/// premium as everyone else. Replaces v2.1's payable msg.value dev
/// buy — the only signature change on this variant.
function create(
string calldata name,
string calldata symbol,
string calldata metadata,
address feeRecipient,
uint256 quoteIn,
uint256 minTokensOut,
bool antiSnipe
) external nonReentrant returns (address token) {
require(bytes(name).length > 0 && bytes(name).length <= 64, "name");
// ticker capped at 12 so every $TICKER stays a clickable X cashtag
require(bytes(symbol).length > 0 && bytes(symbol).length <= 12, "symbol");
require(bytes(metadata).length <= 8192, "metadata too big");
// v2.2 on-chain anti-vamp: the exact (name, ticker) PAIR locks
// protocol-wide for PAIR_COOLDOWN after any launch that uses it
// (helper keeps create()'s stack flat; still no via-ir).
_checkPairCooldown(name, symbol);
// CREATE, not CREATE2: the coin address is unknowable pre-tx, so the
// PoolKey (and pool id) cannot be squatted or front-run. The coin's
// address also decides the pool's currency ordering (delta (b)).
token = address(new PmavCoin(name, symbol)); // 1B minted to the hook
// register + CoinCreated + pool initialize (helper keeps create()'s
// stack flat — this profile compiles without via-ir, the v2.1
// discipline; the extra quoteIn parameter costs the slot v2.1 spent
// on the inline PoolKey local)
_launch(token, feeRecipient == address(0) ? msg.sender : feeRecipient, name, symbol, metadata, antiSnipe);
// dev buy funding: pull the quote up front so the unlock callback can
// settle it
if (quoteIn > 0) _pullDevBuyQuote(quoteIn);
// seed the curve position (+ optional dev buy) inside one unlock
// (poolKeyOf is deterministic, so recomputing it here is exact)
poolManager.unlock(abi.encode(uint8(1), abi.encode(poolKeyOf(token), msg.sender, quoteIn, minTokensOut)));
}
/// @dev registration, the CoinCreated event and the pool initialize for a
/// fresh coin — split out of create() for legacy-codegen stack room.
/// Our own initialize skips beforeInitialize (noSelfCall); every
/// external initialize attempt against this hook reverts there.
function _launch(
address token,
address recipient,
string calldata name,
string calldata symbol,
string calldata metadata,
bool antiSnipe
) internal {
PoolKey memory key = _register(token, recipient, antiSnipe);
emit CoinCreated(token, PoolId.unwrap(key.toId()), msg.sender, recipient, name, symbol, metadata);
if (!antiSnipe) emit AntiSnipeOff(token);
poolManager.initialize(key, token < QUOTE_TOKEN ? SQRT_START_C0 : SQRT_START_Q0);
}
/// @dev pulls the dev-buy quote from the creator by transferFrom.
/// Fee-on-transfer quotes are rejected by measuring the received
/// amount (documented stance: not supported, revert). USDG passes.
function _pullDevBuyQuote(uint256 quoteIn) internal {
uint256 balBefore = IERC20Minimal(QUOTE_TOKEN).balanceOf(address(this));
_safeTransferFrom(QUOTE_TOKEN, msg.sender, address(this), quoteIn);
require(IERC20Minimal(QUOTE_TOKEN).balanceOf(address(this)) - balBefore == quoteIn, "fee on transfer quote");
}
/// @dev v2.2 cooldown gate: case-insensitive over ASCII on the exact
/// (name, ticker) PAIR. First-ever use of a pair (slot 0) always
/// passes, every use re-arms the window. Same ticker + different
/// name NEVER collides here (locked founder decision 2026-07-20).
function _checkPairCooldown(string calldata name, string calldata symbol) internal {
bytes32 ph = _pairHash(name, symbol);
uint64 last = pairLastLaunch[ph];
require(last == 0 || block.timestamp >= uint256(last) + PAIR_COOLDOWN, "name+ticker cooldown");
pairLastLaunch[ph] = uint64(block.timestamp);
}
/// @dev hash of hashes over the ASCII-lowercased name and ticker bytes:
/// keccak(keccak(lowerName) || keccak(lowerTicker)). Fixed width
/// inner hashes make the key COLLISION UNAMBIGUOUS. Non ASCII bytes
/// pass through unchanged (homoglyph lookalikes are a distinct pair
/// on chain and remain a display-layer concern by construction).
function _pairHash(string calldata name, string calldata symbol) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(_lowerHash(bytes(name)), _lowerHash(bytes(symbol))));
}
function _lowerHash(bytes memory b) internal pure returns (bytes32) {
for (uint256 i = 0; i < b.length; i++) {
if (b[i] >= 0x41 && b[i] <= 0x5A) b[i] = bytes1(uint8(b[i]) + 32);
}
return keccak256(b);
}
function _register(address token, address recipient, bool antiSnipe) internal returns (PoolKey memory key) {
key = poolKeyOf(token);
PoolId id = key.toId();
// v2.2: antiSnipe=false freezes a ZERO premium into the pool struct
// (the swap path's _antiSnipeBps already short circuits on window 0)
pools[id] = Pool({
coin: token,
feeRecipient: recipient,
launchBlock: uint64(block.number),
launchTime: uint64(block.timestamp),
snipePeakBps: antiSnipe ? uint16(antiSnipePeakBps) : 0,
snipeWindow: antiSnipe ? uint16(antiSnipeWindow) : 0,
graduated: false,
tokensSold: 0,
raisedWei: 0
});
poolOf[token] = id;
allCoins.push(token);
lastActivity[token] = block.timestamp;
}
function coinCount() external view returns (uint256) {
return allCoins.length;
}
/// canonical PoolKey for a pmav coin — fully deterministic, never stored.
/// The quote ERC20 sorts against the coin address (V4 requires
/// currency0 < currency1), so the ordering is per-coin (delta (b)).
function poolKeyOf(address token) public view returns (PoolKey memory) {
(Currency c0, Currency c1) = token < QUOTE_TOKEN
? (Currency.wrap(token), Currency.wrap(QUOTE_TOKEN))
: (Currency.wrap(QUOTE_TOKEN), Currency.wrap(token));
return PoolKey({
currency0: c0,
currency1: c1,
fee: LPFeeLibrary.DYNAMIC_FEE_FLAG,
tickSpacing: TICK_SPACING,
hooks: this
});
}
/// convenience for tests/UIs: the orientation and curve constants a given
/// coin's pool actually uses
function curveParamsOf(address token)
external
view
returns (bool coinIs0, int24 tickLower, int24 tickUpper, uint160 sqrtStart, uint160 sqrtGrad, uint128 lCurve)
{
coinIs0 = token < QUOTE_TOKEN;
(tickLower, tickUpper) = coinIs0 ? (-TICK_UPPER_Q0, -TICK_LOWER_Q0) : (TICK_LOWER_Q0, TICK_UPPER_Q0);
sqrtStart = coinIs0 ? SQRT_START_C0 : SQRT_START_Q0;
sqrtGrad = coinIs0 ? SQRT_GRAD_C0 : SQRT_GRAD_Q0;
lCurve = coinIs0 ? L_CURVE_C0 : L_CURVE_Q0;
}
// ------------------------------------------------------- unlock callback
/// dispatch for the hook's own unlock operations:
/// 1 = create (seed curve + dev buy), 2 = payout (burn claims + take
/// quote), 3 = collect graduated pool fees
function unlockCallback(bytes calldata data) external onlyPoolManager returns (bytes memory) {
(uint8 action, bytes memory payload) = abi.decode(data, (uint8, bytes));
if (action == 1) {
(PoolKey memory key, address creator, uint256 value, uint256 minTokensOut) =
abi.decode(payload, (PoolKey, address, uint256, uint256));
_createCallback(key, creator, value, minTokensOut);
} else if (action == 2) {
(address to, uint256 amount) = abi.decode(payload, (address, uint256));
poolManager.burn(address(this), QUOTE_ID, amount);
poolManager.take(Currency.wrap(QUOTE_TOKEN), to, amount);
} else if (action == 3) {
(address token) = abi.decode(payload, (address));
_collectCallback(token);
} else {
revert("bad action");
}
return "";
}
function _createCallback(PoolKey memory key, address creator, uint256 value, uint256 minTokensOut) internal {
PoolId id = key.toId();
Pool storage p = pools[id];
address token = p.coin;
bool coinIs0 = token < QUOTE_TOKEN;
(int24 tickLo, int24 tickHi) = coinIs0
? (-TICK_UPPER_Q0, -TICK_LOWER_Q0)
: (TICK_LOWER_Q0, TICK_UPPER_Q0);
// seed the curve: at the start edge the position is 100% tokens
(BalanceDelta d,) = poolManager.modifyLiquidity(
key,
ModifyLiquidityParams({
tickLower: tickLo,
tickUpper: tickHi,
liquidityDelta: int256(uint256(coinIs0 ? L_CURVE_C0 : L_CURVE_Q0)),
salt: 0
}),
""
);
// settle the owed tokens (<= 800M by L construction; no quote owed)
uint256 owedTokens = uint256(uint128(-(coinIs0 ? d.amount0() : d.amount1())));
poolManager.sync(coinIs0 ? key.currency0 : key.currency1);
require(PmavCoin(token).transfer(address(poolManager), owedTokens), "transfer");
poolManager.settle();
// dev buy: a REAL PoolManager swap in the creation block
if (value > 0) _devBuy(key, p, coinIs0, creator, value, minTokensOut);
}
/// Because the hook itself is the swapper, beforeSwap/afterSwap do NOT run
/// (noSelfCall) — fee, premium, cap clamp, ledgers and the Trade event are
/// applied inline here with arithmetic identical to beforeSwap. The quote
/// was already pulled from the creator in create(); it settles into the PM
/// here and any over-cap surplus transfers straight back to the creator.
function _devBuy(
PoolKey memory key,
Pool storage p,
bool coinIs0,
address creator,
uint256 value,
uint256 minTokensOut
) internal {
PoolId id = key.toId();
uint256 feeBps = FEE_BPS + _antiSnipeBps(p); // premium at peak (t = 0)
uint256 gross = value;
uint256 refund = 0;
{
uint256 maxGross = _maxGrossForCap(id, coinIs0, MAX_WALLET, feeBps);
if (gross > maxGross) {
refund = gross - maxGross;
gross = maxGross;
}
}
uint256 fee = gross * feeBps / 10_000;
uint256 net = gross - fee;
require(net > 0, "dust buy");
uint256 tokensOut = _curveBuySwap(key, coinIs0, net);
require(tokensOut >= minTokensOut, "slippage");
require(tokensOut <= MAX_WALLET, "cap invariant");
// settle net (the swap) + fee (real quote tokens into the PoolManager,
// the fee leg immediately re-minted as the hook's ERC6909 fee claim)
poolManager.sync(Currency.wrap(QUOTE_TOKEN));
_safeTransfer(QUOTE_TOKEN, address(poolManager), net + fee);
poolManager.settle();
poolManager.mint(address(this), QUOTE_ID, fee);
_credit(p, fee);
_recordCapBuy(id, tx.origin, tokensOut); // fresh pool: first buy (creator holds 0 coin at create)
p.tokensSold += uint128(tokensOut);
p.raisedWei += uint128(net);
poolManager.take(coinIs0 ? key.currency0 : key.currency1, creator, tokensOut);
_emitTrade(p, id, true, gross, net, tokensOut);
// over-cap surplus: plain ERC20 transfer back (no .call{value}, and a
// standard ERC20 cannot re-enter — the nonReentrant lock guards the
// callback-capable exotic case anyway)
if (refund > 0) _safeTransfer(QUOTE_TOKEN, creator, refund);
}
/// @dev the dev buy's inner pool swap (split out of _devBuy for
/// legacy-codegen stack room): quote in, oriented by the ordering,
/// returns the coin-side fill
function _curveBuySwap(PoolKey memory key, bool coinIs0, uint256 net) internal returns (uint256 tokensOut) {
BalanceDelta sd = poolManager.swap(
key,
SwapParams({
zeroForOne: !coinIs0, // buy: quote in
amountSpecified: -int256(net),
sqrtPriceLimitX96: coinIs0 ? TickMath.MAX_SQRT_PRICE - 1 : TickMath.MIN_SQRT_PRICE + 1
}),
""
);
tokensOut = uint256(uint128(coinIs0 ? sd.amount0() : sd.amount1()));
}
function _emitTrade(Pool storage p, PoolId id, bool isBuy, uint256 gross, uint256 net, uint256 tokens) internal {
(uint160 sqrtNow,,,) = poolManager.getSlot0(id);
emit Trade(p.coin, tx.origin, isBuy, gross, net, tokens, sqrtNow, p.tokensSold, p.raisedWei);
}
// ------------------------------------------------------------------ fees
/// Split of the TOTAL fee (base 1% + any anti-snipe premium): 70% creator /
/// 30% platform, uniform. Platform takes floor(fee * 3 / 10); the creator
/// gets the remainder, so the odd unit rounds to the CREATOR. The premium
/// is NOT special-cased — it splits 70/30 exactly like the base (so the
/// platform also shares in the sniper premium).
function _credit(Pool storage p, uint256 fee) internal {
uint256 platformShare = fee * 3 / 10; // 30% of the total fee (base + premium)
platformFees += platformShare;
creatorFees[p.feeRecipient] += fee - platformShare; // 70%, odd unit to creator
}
function claimCreatorFees() external nonReentrant {
uint256 amount = creatorFees[msg.sender];
require(amount > 0, "nothing to claim");
creatorFees[msg.sender] = 0;
// claiming is the natural "I'm alive" signal: it protects every coin
// paying this recipient from a CTO. only msg.sender can stamp itself.
lastClaim[msg.sender] = block.timestamp;
poolManager.unlock(abi.encode(uint8(2), abi.encode(msg.sender, amount)));
emit CreatorFeesClaimed(msg.sender, amount);
}
/// @notice Pull a refund queued by the ruling-19.B waterfall (branch 2:
/// an over-cap buy through a settle-after router while the
/// PoolManager's quote float could not cover the instant take).
/// Permissionless pull, claimCreatorFees shape: burns the hook's
/// ERC6909 claims and pays real quote tokens — by claim time the
/// buyer's own settle has long since delivered the backing quote.
function claimRefund() external nonReentrant {
uint256 amount = refunds[msg.sender];
require(amount > 0, "nothing to claim");
refunds[msg.sender] = 0;
poolManager.unlock(abi.encode(uint8(2), abi.encode(msg.sender, amount)));
emit RefundClaimed(msg.sender, amount);
}
function withdrawPlatformFees(address to) external onlyOwner nonReentrant {
uint256 amount = platformFees;
require(amount > 0, "nothing to withdraw");
platformFees = 0;
poolManager.unlock(abi.encode(uint8(2), abi.encode(to, amount)));
emit PlatformFeesWithdrawn(to, amount);
}
/// @notice Realize a graduated pool's accrued 1% LP fees from the locked
/// full-range position. Permissionless — anyone pokes (v1 locker
/// parity). Quote side split 70% creator / 30% platform into the
/// pull ledgers (so an exotic recipient can never brick the
/// collect); coin side split the same way and transferred directly
/// (PmavCoin transfers cannot revert or reenter).
function collectPoolFees(address token) external nonReentrant {
Pool storage p = pools[poolOf[token]];
require(p.coin == token && token != address(0), "unknown coin");
require(p.graduated, "not graduated");
poolManager.unlock(abi.encode(uint8(3), abi.encode(token)));
}
function _collectCallback(address token) internal {
PoolKey memory key = poolKeyOf(token);
Pool storage p = pools[key.toId()];
bool coinIs0 = token < QUOTE_TOKEN;
// a zero-liquidity-delta poke realizes feesAccrued as caller deltas
(BalanceDelta fees,) = poolManager.modifyLiquidity(
key,
ModifyLiquidityParams({
tickLower: FULL_TICK_LOWER,
tickUpper: FULL_TICK_UPPER,
liquidityDelta: 0,
salt: 0
}),
""
);
uint256 quoteFees = uint256(uint128(coinIs0 ? fees.amount1() : fees.amount0()));
uint256 coinFees = uint256(uint128(coinIs0 ? fees.amount0() : fees.amount1()));
// graduated-pool LP fees split 70% creator / 30% platform (= 3/10
// platform), odd unit to the CREATOR — identical rounding discipline
// to _credit (there is no anti-snipe premium here).
uint256 platQuote = quoteFees * 3 / 10;
if (quoteFees > 0) {
poolManager.mint(address(this), QUOTE_ID, quoteFees);
creatorFees[p.feeRecipient] += quoteFees - platQuote;
platformFees += platQuote;
}
uint256 platCoin = coinFees * 3 / 10;
if (coinFees > 0) {
poolManager.take(coinIs0 ? key.currency0 : key.currency1, address(this), coinFees);
if (coinFees - platCoin > 0) require(PmavCoin(token).transfer(p.feeRecipient, coinFees - platCoin), "t1");
if (platCoin > 0) require(PmavCoin(token).transfer(owner, platCoin), "t2");
}
emit PoolFeesCollected(token, p.feeRecipient, quoteFees - platQuote, coinFees - platCoin, platQuote, platCoin);
}
// ------------------------------------------------------------ governance
// line-for-line ports from audited v1 Pmav.sol — moved, not rewritten
function setFeeRecipient(address token, address newRecipient) external {
Pool storage p = pools[poolOf[token]];
require(p.coin == token && token != address(0), "unknown coin");
require(msg.sender == p.feeRecipient, "not fee recipient");
require(newRecipient != address(0), "zero addr");
require(!feeRecipientLocked[token], "fee recipient locked");
lastActivity[token] = block.timestamp;
emit FeeRecipientChanged(token, p.feeRecipient, newRecipient);
p.feeRecipient = newRecipient;
}
/// @notice Permanently freeze the CURRENT fee recipient of a coin. One-way.
function lockFeeRecipient(address token) external {
Pool storage p = pools[poolOf[token]];
require(p.coin == token && token != address(0), "unknown coin");
require(msg.sender == p.feeRecipient, "not fee recipient");
require(!feeRecipientLocked[token], "already locked");
feeRecipientLocked[token] = true;
lastActivity[token] = block.timestamp;
emit FeeRecipientLockedEvent(token, p.feeRecipient);
}
/// @notice Atomically REASSIGN the fee recipient and permanently lock it.
function lockFeeRecipientTo(address token, address newRecipient) external {
Pool storage p = pools[poolOf[token]];
require(p.coin == token && token != address(0), "unknown coin");
require(msg.sender == p.feeRecipient, "not fee recipient");
require(newRecipient != address(0), "zero addr");
require(!feeRecipientLocked[token], "already locked");
lastActivity[token] = block.timestamp;
emit FeeRecipientChanged(token, p.feeRecipient, newRecipient);
p.feeRecipient = newRecipient;
feeRecipientLocked[token] = true;
emit FeeRecipientLockedEvent(token, newRecipient);
}
/// @notice CTO (community takeover): redirect an abandoned coin's FUTURE
/// creator rewards to a community lead. The one rail no review can
/// waive: the current DEV must be provably inactive — no fee claim
/// and no per-coin steward action for CTO_INACTIVITY. Trading does
/// NOT protect a dev. Locked coins are immune by design.
function proposeCtoRedirect(address token, address newRecipient) external onlyOwner {
Pool storage p = pools[poolOf[token]];
require(p.coin == token && token != address(0), "unknown coin");
require(newRecipient != address(0), "zero addr");
require(newRecipient != owner, "owner cannot self target");
require(!feeRecipientLocked[token], "fee recipient locked");
uint256 devActive = lastActivity[token];
uint256 claimed = lastClaim[p.feeRecipient];
if (claimed > devActive) devActive = claimed;
require(block.timestamp >= devActive + CTO_INACTIVITY, "dev still active");
ctoProposals[token] = CtoProposal({newRecipient: newRecipient, proposedAt: uint64(block.timestamp)});
emit CtoRedirectProposed(token, p.feeRecipient, newRecipient, block.timestamp + CTO_VETO_DELAY);
}
/// @notice CTO step 2 of 2: EXECUTE after the 12h veto window. ANY dev
/// liveness signal newer than the proposal (one fee claim, one
/// steward action, a lock) cancels it — no silent seizure path.
function executeCtoRedirect(address token) external onlyOwner {
Pool storage p = pools[poolOf[token]];
require(p.coin == token && token != address(0), "unknown coin");
CtoProposal memory prop = ctoProposals[token];
require(prop.newRecipient != address(0), "no proposal");
require(block.timestamp >= uint256(prop.proposedAt) + CTO_VETO_DELAY, "veto window open");
require(!feeRecipientLocked[token], "fee recipient locked");
require(lastActivity[token] < prop.proposedAt, "vetoed: dev acted");
require(lastClaim[p.feeRecipient] < prop.proposedAt, "vetoed: dev claimed");
delete ctoProposals[token];
lastActivity[token] = block.timestamp; // fresh window for the new lead
emit FeeRecipientChanged(token, p.feeRecipient, prop.newRecipient);
emit CtoRedirect(token, p.feeRecipient, prop.newRecipient);
p.feeRecipient = prop.newRecipient;
}
function setOwner(address newOwner) external onlyOwner {
require(newOwner != address(0), "zero addr");
emit OwnerChanged(owner, newOwner);
owner = newOwner;
}
/// @notice Tune the anti-snipe FACTORY DEFAULTS, bounded by the hard caps.
/// TIGHTENED vs v1: affects FUTURE launches only — every live
/// pool's premium/window were frozen into its struct at create().
function setAntiSnipeDefaults(uint256 peakBps, uint256 window) external onlyOwner {
require(peakBps <= ANTI_SNIPE_MAX_BPS, "peak too high");
require(window <= ANTI_SNIPE_MAX_WINDOW, "window too long");
antiSnipePeakBps = peakBps;
antiSnipeWindow = window;
emit AntiSnipeChanged(peakBps, window);
}
// ---------------------------------------------------------------- quotes
/// @notice Mirror of the buy path for UI parity with v1. APPROXIMATE by a
/// few parts in 1e15: the pool consumes input in tick-word chunks
/// with per-chunk round-up, which a closed-form view cannot
/// replicate — use V4Quoter (which simulates the real swap,
/// hook deltas included) for an exact minTokensOut. `refund` is
/// the curve-completion surplus only; the per-wallet cap clamp
/// depends on the buyer and is not modeled here (v1 parity).
/// `quoteGross` and all returns are RAW QUOTE UNITS.
function quoteBuy(address token, uint256 quoteGross)
external
view
returns (uint256 tokensOut, uint256 fee, uint256 refund)
{
PoolId id = poolOf[token];
Pool storage p = pools[id];
require(p.coin == token && token != address(0) && !p.graduated, "not on curve");
bool coinIs0 = token < QUOTE_TOKEN;
uint128 lCurve = coinIs0 ? L_CURVE_C0 : L_CURVE_Q0;
uint160 sqrtGrad = coinIs0 ? SQRT_GRAD_C0 : SQRT_GRAD_Q0;
uint256 feeBps = FEE_BPS + _antiSnipeBps(p);
uint160 sqrtP = _effSqrtP(id, coinIs0);
// v2.2 (audit L1): fee base bounded by the gross the curve can
// actually consume to graduation — mirrors the beforeSwap clamp, so
// an oversized completing buy is quoted AND charged on USED gross.
{
uint256 clampNet = coinIs0
? SqrtPriceMath.getAmount1Delta(sqrtP, sqrtGrad, lCurve, true)
: SqrtPriceMath.getAmount0Delta(sqrtGrad, sqrtP, lCurve, true);
uint256 maxFeeGross = FullMath.mulDivRoundingUp(clampNet, 10_000, 10_000 - feeBps);
fee = (quoteGross > maxFeeGross ? maxFeeGross : quoteGross) * feeBps / 10_000;
}
uint256 net = quoteGross - fee;
require(net > 0, "dust buy");
// quote in: currency0 in (price down) for Q0 pools, currency1 in
// (price up) for C0 pools
uint160 sqrtNext = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, lCurve, net, !coinIs0);
if (coinIs0 ? sqrtNext > sqrtGrad : sqrtNext < sqrtGrad) {
// completing buy: only the quote that finishes the curve is consumed
uint256 maxNet = coinIs0
? SqrtPriceMath.getAmount1Delta(sqrtP, sqrtGrad, lCurve, true)
: SqrtPriceMath.getAmount0Delta(sqrtGrad, sqrtP, lCurve, true);
refund = quoteGross - fee - maxNet;
tokensOut = coinIs0
? SqrtPriceMath.getAmount0Delta(sqrtP, sqrtGrad, lCurve, false)
: SqrtPriceMath.getAmount1Delta(sqrtGrad, sqrtP, lCurve, false);
} else {
tokensOut = coinIs0
? SqrtPriceMath.getAmount0Delta(sqrtP, sqrtNext, lCurve, false)
: SqrtPriceMath.getAmount1Delta(sqrtNext, sqrtP, lCurve, false);
}
}
/// @notice returns are RAW QUOTE UNITS
function quoteSell(address token, uint256 tokenAmount) external view returns (uint256 quoteNet, uint256 fee) {
PoolId id = poolOf[token];
Pool storage p = pools[id];
require(p.coin == token && token != address(0) && !p.graduated, "not on curve");
require(tokenAmount > 0, "zero amount");
bool coinIs0 = token < QUOTE_TOKEN;
uint128 lCurve = coinIs0 ? L_CURVE_C0 : L_CURVE_Q0;
uint160 sqrtStart = coinIs0 ? SQRT_START_C0 : SQRT_START_Q0;
uint160 sqrtP = _effSqrtP(id, coinIs0);
// token in: currency1 in (price up) for Q0 pools, currency0 in
// (price down) for C0 pools
uint160 sqrtNext = SqrtPriceMath.getNextSqrtPriceFromInput(sqrtP, lCurve, tokenAmount, coinIs0);
// beyond the curve start the pool stops paying
if (coinIs0 ? sqrtNext < sqrtStart : sqrtNext > sqrtStart) sqrtNext = sqrtStart;
uint256 quoteGross = coinIs0
? SqrtPriceMath.getAmount1Delta(sqrtNext, sqrtP, lCurve, false)
: SqrtPriceMath.getAmount0Delta(sqrtP, sqrtNext, lCurve, false);
fee = quoteGross * FEE_BPS / 10_000;
quoteNet = quoteGross - fee;
}
/// @notice spot price in RAW QUOTE UNITS per whole (1e18) token, and
/// market cap in raw quote units. v1-shaped for the site; `pool`
/// is the PoolManager once graduated (v1 semantics: nonzero pool
/// == trade on the DEX). Return names keep the v2 ABI shape; the
/// values are quote units at QUOTE_DECIMALS.
function state(address token)
external
view
returns (
uint256 priceWei,
uint256 mcapWei,
uint256 ethReserve,
uint256 tokensSold,
uint256 progressBps,
bool graduated,
address pool
)
{
PoolId id = poolOf[token];
Pool storage p = pools[id];
require(p.coin == token && token != address(0), "unknown coin");
(uint160 sqrtP,,,) = poolManager.getSlot0(id);
// quote per whole token. Q0 pools: price(coin/quote) = (sqrtP/2^96)^2,
// so quote per 1e18 token-wei = 1e18 * 2^192 / sqrtP^2; C0 pools:
// price(quote/coin) = (sqrtP/2^96)^2, so quote per 1e18 token-wei =
// 1e18 * sqrtP^2 / 2^192. Both computed as two chained mulDivs so no
// sqrtP magnitude can overflow the naive sqrtP*sqrtP product.
if (token < QUOTE_TOKEN) {
priceWei = FullMath.mulDiv(FullMath.mulDiv(sqrtP, 1e18, FixedPoint96.Q96), sqrtP, FixedPoint96.Q96);
} else {
priceWei = FullMath.mulDiv(FullMath.mulDiv(FixedPoint96.Q96, 1e18, sqrtP), FixedPoint96.Q96, sqrtP);
}
mcapWei = priceWei * 1_000_000_000;
ethReserve = p.raisedWei;
tokensSold = p.tokensSold;
progressBps = uint256(p.tokensSold) * 10_000 / CURVE_SUPPLY;
graduated = p.graduated;
pool = p.graduated ? address(poolManager) : address(0);
}
function feeRecipientOf(address token) external view returns (address) {
return pools[poolOf[token]].feeRecipient;
}
// ------------------------------------------------------------- internals
function _abs(int256 x) internal pure returns (uint256) {
return x < 0 ? uint256(-x) : uint256(x);
}
/// @notice v2.2: whether this coin carries the decaying anti snipe
/// premium (the creator's public choice at create()).
function antiSnipeEnabled(address token) external view returns (bool) {
Pool storage p = pools[poolOf[token]];
require(p.coin == token && token != address(0), "unknown coin");
return p.snipePeakBps > 0 && p.snipeWindow > 0;
}
/// v2.2 (audit L2): opt in refund beneficiary carried in hookData.
/// EXACTLY 32 bytes decodes as an address by raw truncation (never
/// abi.decode: malformed hookData must IGNORE, not revert a swap).
function _refundBeneficiary(bytes calldata hookData) internal pure returns (address) {
if (hookData.length != 32) return address(0);
return address(uint160(uint256(bytes32(hookData[0:32]))));
}
/// current curve price for quote/clamp math, bounded to the curve range:
/// a sell can park the spot price BEYOND the curve start through empty
/// liquidity (above it on Q0 pools, below it on C0 pools); buys from
/// there walk back for free, so all token/quote math must start at the
/// start edge, not the empty-space price
function _effSqrtP(PoolId id, bool coinIs0) internal view returns (uint160 sqrtP) {
(sqrtP,,,) = poolManager.getSlot0(id);
if (coinIs0) {
if (sqrtP < SQRT_START_C0) sqrtP = SQRT_START_C0;
} else {
if (sqrtP > SQRT_START_Q0) sqrtP = SQRT_START_Q0;
}
}
/// max gross quote (fee included) a first-hour buy may spend so that the
/// delivered tokens never exceed capLeft. Rounding discipline (test
/// enforced): the sqrt target rounds TOWARD the current price (fewer
/// tokens) and the quote amount rounds DOWN, so core's forward math can
/// never deliver > capLeft.
function _maxGrossForCap(PoolId id, bool coinIs0, uint256 capLeft, uint256 feeBps)
internal
view
returns (uint256 maxGross)
{
uint160 sqrtP = _effSqrtP(id, coinIs0);
uint160 sqrtGrad = coinIs0 ? SQRT_GRAD_C0 : SQRT_GRAD_Q0;
uint128 lCurve = coinIs0 ? L_CURVE_C0 : L_CURVE_Q0;
uint256 maxNet;
bool gradBound;
if (coinIs0) {
// tokens are currency0: capLeft = L*Q96*(1/sqrtP - 1/target), so
// target = L*Q96*sqrtP / (L*Q96 - capLeft*sqrtP). The quotient
// FLOORS => target rounds DOWN (toward sqrtP) => tokens at target
// <= capLeft.
if (sqrtP >= sqrtGrad) return 0;
uint256 lQ96 = uint256(lCurve) << 96;
uint256 sold = capLeft * sqrtP; // < 2^244 across the whole envelope
gradBound = sold >= lQ96;
uint160 sqrtTarget = sqrtGrad;
if (!gradBound) {
uint256 t = FullMath.mulDiv(lQ96, sqrtP, lQ96 - sold);
if (t >= sqrtGrad) gradBound = true;
else sqrtTarget = uint160(t);
}
// when the graduation edge binds the fill is bounded by the curve
// itself, so rounding UP is safe (it just guarantees graduation)
maxNet = SqrtPriceMath.getAmount1Delta(sqrtP, sqrtTarget, lCurve, gradBound);
} else {
// tokens are currency1 (the v2 shape verbatim): sqrt price after
// the position hands out capLeft tokens (quotient floored =>
// target rounds UP => tokens at target <= capLeft)
if (sqrtP <= sqrtGrad) return 0;
uint256 quotient = FullMath.mulDiv(capLeft, FixedPoint96.Q96, lCurve);
gradBound = quotient >= sqrtP || sqrtP - quotient <= sqrtGrad;
uint160 sqrtTarget = gradBound ? sqrtGrad : uint160(sqrtP - quotient);
maxNet = SqrtPriceMath.getAmount0Delta(sqrtTarget, sqrtP, lCurve, gradBound);
}
if (maxNet == 0) return 0;
if (gradBound) {
// v2.2 FIX (found by the port suite, red test
// test_completing_buy_graduates_in_one_tx): when the graduation
// edge binds, tokens delivered are bounded by the CURVE (remaining
// curve <= capLeft by the gradBound condition), so round the gross
// UP and SKIP the walk down. The floor + walk down combination
// could leave a completing buy a sub wei hair above the edge
// (strict trigger misses; the coin failed to graduate in the same
// tx). A wei generous net just walks price past the edge into
// EMPTY liquidity, where input is never consumed and flows back
// through the router (the v2.1 post hour overshoot semantics the
// _graduate boundary repair already handles) -- it can never over
// deliver tokens and it guarantees same tx graduation.
return FullMath.mulDivRoundingUp(maxNet, 10_000, 10_000 - feeBps);
}
maxGross = FullMath.mulDiv(maxNet, 10_000, 10_000 - feeBps);
// exactness guard: the swap path will charge fee = floor(g*f/1e4) and
// hand the pool g - fee; walk g down (<=2 iterations) until that net
// cannot exceed maxNet
while (maxGross > 0 && maxGross - (maxGross * feeBps / 10_000) > maxNet) {
maxGross--;
}
}
// ---- v2.2 HARD 2% wallet cap (founder ruling 2026-07-20) --------------
// No wallet may hold more than 2% as a result of buying, and no tx.origin
// may ACQUIRE more than 2% through this pool in a single transaction —
// bundlers, MEV bots, snipers, any custom contract, all bound. Over-cap
// buys fill to exactly 2% and refund the surplus (fee only on the 2%).
//
// The cap binds on `held = startBalance + boughtTx`:
// * startBalance — the COIN balance (18dp, either orientation) tx.origin
// held at the START of this transaction, snapshotted at the FIRST cap
// touch (while boughtTx is still 0) and then FIXED. It captures any
// pre-existing holding a buy must not push past 2%.
// * boughtTx — a MONOTONIC per (pool, origin) TRANSIENT counter of
// everything tx.origin has bought through this pool this transaction,
// NEVER reset.
// The two sets are DISJOINT — startBalance excludes this-tx buys (not yet
// settled into balanceOf), boughtTx IS this-tx buys — so their SUM is the
// exact acquisition-inclusive holding: no double count of a settled buy, no
// under count of a warm wallet that bundles buys in one unlock. A FIXED
// start snapshot plus a monotonic never-reset counter means no balance move
// mid-tx (a 1-wei delivery to origin, a full delivery, a transfer to a
// stash) can re-open the cap. Transient clears at tx end, so a later tx
// re-snapshots startBalance from the live balance (a sell/transfer away in a
// separate tx frees capacity).
//
// Documented residual (unpreventable without token transfer restrictions,
// which stay rejected for scanner cleanliness): spreading buys across many
// transactions/wallets and funneling to one address via raw ERC20 transfers
// (incl. a transfer INTO origin AFTER the start snapshot in the same tx).
// The cap is a hard per-transaction acquisition + start-of-tx holding bound,
// not a cross-transaction identity bound.
function _capBoughtSlot(PoolId id, address origin) private pure returns (bytes32 slot) {
slot = keccak256(abi.encode("pmav.cap.bought", id, origin));
}
function _capStartSlot(PoolId id, address origin) private pure returns (bytes32 slot) {
slot = keccak256(abi.encode("pmav.cap.start", id, origin));
}
/// tokens tx.origin effectively holds against the cap = its start-of-tx COIN
/// balance (snapshotted at the first cap touch, when boughtTx is still 0)
/// PLUS everything bought through this pool this tx (a monotonic transient
/// counter). The SUM of these two disjoint sets: never double counts a
/// settled buy, never under counts a warm wallet bundling buys, and no
/// balance move can re-open the cap (both terms fixed/monotonic).
function _capHeld(PoolId id, address coin, address origin) internal returns (uint256 held) {
bytes32 bSlot = _capBoughtSlot(id, origin);
bytes32 sSlot = _capStartSlot(id, origin);
uint256 bought;
assembly ("memory-safe") {
bought := tload(bSlot)
}
uint256 start;
if (bought == 0) {
// first cap touch this tx: snapshot the pre-buy balance and fix it
start = PmavCoin(coin).balanceOf(origin);
assembly ("memory-safe") {
tstore(sSlot, start)
}
} else {
assembly ("memory-safe") {
start := tload(sSlot)
}
}
held = start + bought;
}
function _recordCapBuy(PoolId id, address origin, uint256 amount) internal {
bytes32 bSlot = _capBoughtSlot(id, origin);
uint256 bought;
assembly ("memory-safe") {
bought := tload(bSlot)
}
assembly ("memory-safe") {
tstore(bSlot, add(bought, amount))
}
}
/// Anti-snipe premium (bps) at the current time for a pool: linear decay
/// from the pool's FROZEN peak at launch to 0 at its frozen window edge.
function _antiSnipeBps(Pool storage p) internal view returns (uint256) {
uint256 window = p.snipeWindow;
if (window == 0) return 0;
uint256 elapsed = block.timestamp - p.launchTime;
if (elapsed >= window) return 0;
return uint256(p.snipePeakBps) * (window - elapsed) / window;
}
/// standard Babylonian integer sqrt (floor). Only used once, in the
/// constructor's curve derivation.
function _sqrt(uint256 x) internal pure returns (uint256 z) {
if (x == 0) return 0;
uint256 y = x;
z = 1;
// seed z near sqrt(x) by halving the bit length
if (y >= 1 << 128) {
y >>= 128;
z <<= 64;
}
if (y >= 1 << 64) {
y >>= 64;
z <<= 32;
}
if (y >= 1 << 32) {
y >>= 32;
z <<= 16;
}
if (y >= 1 << 16) {
y >>= 16;
z <<= 8;
}
if (y >= 1 << 8) {
y >>= 8;
z <<= 4;
}
if (y >= 1 << 4) {
y >>= 4;
z <<= 2;
}
if (y >= 1 << 2) {
z <<= 1;
}
z = (z + x / z) >> 1;
z = (z + x / z) >> 1;
z = (z + x / z) >> 1;
z = (z + x / z) >> 1;
z = (z + x / z) >> 1;
z = (z + x / z) >> 1;
z = (z + x / z) >> 1;
// floor correction (Babylonian can land one above)
if (z > x / z) z--;
}
/// round a tick to the NEAREST TICK_SPACING multiple (ties away from
/// zero) — the alignment discipline that produced v2's [176620, 204350]
function _alignNearest(int24 tick) internal pure returns (int24) {
int24 r = tick % TICK_SPACING;
int24 base = tick - r;
if (r >= 5) base += TICK_SPACING;
else if (r <= -5) base -= TICK_SPACING;
return base;
}
/// minimal safe-ERC20 (USDT-style missing-return tolerated, reverts on
/// explicit false or failed call) — the hook's only direct quote moves
/// are the dev-buy pull, its PM settle leg, and the dev-buy surplus refund
function _safeTransfer(address token, address to, uint256 amount) internal {
(bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0xa9059cbb, to, amount));
require(ok && (ret.length == 0 || abi.decode(ret, (bool))), "quote transfer failed");
}
function _safeTransferFrom(address token, address from, address to, uint256 amount) internal {
(bool ok, bytes memory ret) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, amount));
require(ok && (ret.length == 0 || abi.decode(ret, (bool))), "quote transferFrom failed");
}
// NOTE: no receive() on this variant — the quote is an ERC20, no code
// path handles native ETH, and any direct ETH send reverts by default.
}[
{
"type": "constructor",
"inputs": [
{
"name": "_manager",
"type": "address",
"internalType": "contract IPoolManager"
},
{
"name": "_owner",
"type": "address",
"internalType": "address"
},
{
"name": "_quoteToken",
"type": "address",
"internalType": "address"
},
{
"name": "_quoteDecimals",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "_gradRaise",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "HookNotImplemented",
"type": "error",
"inputs": []
},
{
"name": "NotPoolManager",
"type": "error",
"inputs": []
},
{
"name": "AntiSnipeChanged",
"type": "event",
"inputs": [
{
"name": "peakBps",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "window",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "AntiSnipeOff",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "CoinCreated",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "creator",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "feeRecipient",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "name",
"type": "string",
"indexed": false,
"internalType": "string"
},
{
"name": "symbol",
"type": "string",
"indexed": false,
"internalType": "string"
},
{
"name": "metadata",
"type": "string",
"indexed": false,
"internalType": "string"
}
],
"anonymous": false
},
{
"name": "CreatorFeesClaimed",
"type": "event",
"inputs": [
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "CtoRedirect",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "oldRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "CtoRedirectProposed",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "oldRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "executableAt",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "FeeRecipientChanged",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "oldRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "FeeRecipientLockedEvent",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "Graduated",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "ethInPool",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "tokensInPool",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "OwnerChanged",
"type": "event",
"inputs": [
{
"name": "oldOwner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "newOwner",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "PlatformFeesWithdrawn",
"type": "event",
"inputs": [
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "PoolFeesCollected",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "creatorRecipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "creatorWei",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "creatorTokens",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "platformWei",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "platformTokens",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "RefundClaimed",
"type": "event",
"inputs": [
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "RefundQueued",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "Trade",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "trader",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "isBuy",
"type": "bool",
"indexed": false,
"internalType": "bool"
},
{
"name": "ethGross",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "ethNet",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "tokenAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "sqrtPriceX96",
"type": "uint160",
"indexed": false,
"internalType": "uint160"
},
{
"name": "tokensSold",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
},
{
"name": "raisedWei",
"type": "uint128",
"indexed": false,
"internalType": "uint128"
}
],
"anonymous": false
},
{
"name": "ANTI_SNIPE_MAX_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "ANTI_SNIPE_MAX_WINDOW",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "CTO_INACTIVITY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "CTO_VETO_DELAY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "CURVE_SUPPLY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "FEE_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "FULL_TICK_LOWER",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "FULL_TICK_UPPER",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "GRADUATED_LP_FEE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint24",
"internalType": "uint24"
}
],
"stateMutability": "view"
},
{
"name": "GRADUATION_GAS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "GRAD_RAISE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "LP_SUPPLY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "L_CURVE_C0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "L_CURVE_Q0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "MAX_WALLET",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "PAIR_COOLDOWN",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "QUOTE_DECIMALS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "QUOTE_TOKEN",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "SQRT_GRAD_C0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint160",
"internalType": "uint160"
}
],
"stateMutability": "view"
},
{
"name": "SQRT_GRAD_Q0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint160",
"internalType": "uint160"
}
],
"stateMutability": "view"
},
{
"name": "SQRT_START_C0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint160",
"internalType": "uint160"
}
],
"stateMutability": "view"
},
{
"name": "SQRT_START_Q0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint160",
"internalType": "uint160"
}
],
"stateMutability": "view"
},
{
"name": "TICK_LOWER_Q0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "TICK_SPACING",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "TICK_UPPER_Q0",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "TOTAL_SUPPLY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "afterAddLiquidity",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "liquidityDelta",
"type": "int256",
"internalType": "int256"
},
{
"name": "salt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"internalType": "struct ModifyLiquidityParams"
},
{
"name": "delta",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "feesAccrued",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BalanceDelta"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterDonate",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "amount0",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterInitialize",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "sqrtPriceX96",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "tick",
"type": "int24",
"internalType": "int24"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterRemoveLiquidity",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "liquidityDelta",
"type": "int256",
"internalType": "int256"
},
{
"name": "salt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"internalType": "struct ModifyLiquidityParams"
},
{
"name": "delta",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "feesAccrued",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BalanceDelta"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterSwap",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "zeroForOne",
"type": "bool",
"internalType": "bool"
},
{
"name": "amountSpecified",
"type": "int256",
"internalType": "int256"
},
{
"name": "sqrtPriceLimitX96",
"type": "uint160",
"internalType": "uint160"
}
],
"internalType": "struct SwapParams"
},
{
"name": "delta",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int128",
"internalType": "int128"
}
],
"stateMutability": "nonpayable"
},
{
"name": "allCoins",
"type": "function",
"inputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "antiSnipeEnabled",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "antiSnipePeakBps",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "antiSnipeWindow",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "beforeAddLiquidity",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "liquidityDelta",
"type": "int256",
"internalType": "int256"
},
{
"name": "salt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"internalType": "struct ModifyLiquidityParams"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeDonate",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "amount0",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "amount1",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeInitialize",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "sqrtPriceX96",
"type": "uint160",
"internalType": "uint160"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeRemoveLiquidity",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "liquidityDelta",
"type": "int256",
"internalType": "int256"
},
{
"name": "salt",
"type": "bytes32",
"internalType": "bytes32"
}
],
"internalType": "struct ModifyLiquidityParams"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeSwap",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "key",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
},
{
"name": "params",
"type": "tuple",
"components": [
{
"name": "zeroForOne",
"type": "bool",
"internalType": "bool"
},
{
"name": "amountSpecified",
"type": "int256",
"internalType": "int256"
},
{
"name": "sqrtPriceLimitX96",
"type": "uint160",
"internalType": "uint160"
}
],
"internalType": "struct SwapParams"
},
{
"name": "hookData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BeforeSwapDelta"
},
{
"name": "",
"type": "uint24",
"internalType": "uint24"
}
],
"stateMutability": "nonpayable"
},
{
"name": "claimCreatorFees",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "claimRefund",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "coinCount",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "collectPoolFees",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "create",
"type": "function",
"inputs": [
{
"name": "name",
"type": "string",
"internalType": "string"
},
{
"name": "symbol",
"type": "string",
"internalType": "string"
},
{
"name": "metadata",
"type": "string",
"internalType": "string"
},
{
"name": "feeRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "quoteIn",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "minTokensOut",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "antiSnipe",
"type": "bool",
"internalType": "bool"
}
],
"outputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "nonpayable"
},
{
"name": "creatorFees",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "ctoProposals",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "newRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "proposedAt",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"name": "curveParamsOf",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "coinIs0",
"type": "bool",
"internalType": "bool"
},
{
"name": "tickLower",
"type": "int24",
"internalType": "int24"
},
{
"name": "tickUpper",
"type": "int24",
"internalType": "int24"
},
{
"name": "sqrtStart",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "sqrtGrad",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "lCurve",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "executeCtoRedirect",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "feeRecipientLocked",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "feeRecipientOf",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "getHookPermissions",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "beforeInitialize",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterInitialize",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeAddLiquidity",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterAddLiquidity",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeRemoveLiquidity",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterRemoveLiquidity",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeSwap",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterSwap",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeDonate",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterDonate",
"type": "bool",
"internalType": "bool"
},
{
"name": "beforeSwapReturnDelta",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterSwapReturnDelta",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterAddLiquidityReturnDelta",
"type": "bool",
"internalType": "bool"
},
{
"name": "afterRemoveLiquidityReturnDelta",
"type": "bool",
"internalType": "bool"
}
],
"internalType": "struct Hooks.Permissions"
}
],
"stateMutability": "pure"
},
{
"name": "lastActivity",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "lastClaim",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "lockFeeRecipient",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "lockFeeRecipientTo",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "newRecipient",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "owner",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "pairLastLaunch",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"name": "platformFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "poolKeyOf",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "currency0",
"type": "address",
"internalType": "Currency"
},
{
"name": "currency1",
"type": "address",
"internalType": "Currency"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
},
{
"name": "hooks",
"type": "address",
"internalType": "contract IHooks"
}
],
"internalType": "struct PoolKey"
}
],
"stateMutability": "view"
},
{
"name": "poolManager",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IPoolManager"
}
],
"stateMutability": "view"
},
{
"name": "poolOf",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"stateMutability": "view"
},
{
"name": "pools",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "coin",
"type": "address",
"internalType": "address"
},
{
"name": "feeRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "launchBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "launchTime",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "snipePeakBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "snipeWindow",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "graduated",
"type": "bool",
"internalType": "bool"
},
{
"name": "tokensSold",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "raisedWei",
"type": "uint128",
"internalType": "uint128"
}
],
"stateMutability": "view"
},
{
"name": "proposeCtoRedirect",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "newRecipient",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "quoteBuy",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "quoteGross",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "tokensOut",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "fee",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "refund",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "quoteSell",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "tokenAmount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "quoteNet",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "fee",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "refunds",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "setAntiSnipeDefaults",
"type": "function",
"inputs": [
{
"name": "peakBps",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "window",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setFeeRecipient",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "newRecipient",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setOwner",
"type": "function",
"inputs": [
{
"name": "newOwner",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "state",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "priceWei",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "mcapWei",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "ethReserve",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "tokensSold",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "progressBps",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "graduated",
"type": "bool",
"internalType": "bool"
},
{
"name": "pool",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "unlockCallback",
"type": "function",
"inputs": [
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "nonpayable"
},
{
"name": "withdrawPlatformFees",
"type": "function",
"inputs": [
{
"name": "to",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
}
]0x608060405234801561000f575f5ffd5b5060043610610421575f3560e01c8063800939ab1161022c578063c27ca31811610135578063df1b80ae116100bf578063ec3889b511610084578063ec3889b514610dbc578063edff74d014610dcf578063f07e96b314610df6578063fcba2b2914610e15578063ffc8cc5314610e28575f5ffd5b8063df1b80ae14610d55578063df7787a414610d68578063dfcee7d214610d7a578063e1b4af6914610aa7578063e23801f514610db3575f5ffd5b8063d49ed0bc11610105578063d49ed0bc14610c6f578063d98b2f5c14610c96578063da725cc614610cbe578063dc4c90d314610d1b578063dc98354e14610d42575f5ffd5b8063c27ca31814610aea578063c38bd15c14610b4b578063c4e833ce14610b5e578063ced3128514610c52575f5ffd5b8063aeb33de3116101b6578063b5545a3c11610186578063b5545a3c14610a9f578063b6a8b0fa14610aa7578063bc3da53514610aba578063bf333f2c14610ad9578063c1db1b6214610ae1575f5ffd5b8063aeb33de31461093a578063af73cc4214610961578063b47b2fb11461096a578063b5217bb4146109a0575f5ffd5b80639016af09116101fc5780639016af09146108c9578063902d55a5146108e857806391dd7346146108fb578063988b1fa71461091b5780639f063efc146107dc575f5ffd5b8063800939ab14610883578063847a74ad1461088d5780638652edf9146108965780638da5cb5b146108b6575f5ffd5b806331e658a51161032e578063575e24b4116102b85780636c2bbe7e116102885780636c2bbe7e146107dc5780636fe7e6eb1461080f578063741965d81461082257806378892cea146108355780637f3ae11d1461085c575f5ffd5b8063575e24b4146107655780635c16e15e146107a3578063670171fd146107c2578063678fd289146107d4575f5ffd5b80633cfc7ede116102fe5780633cfc7ede146106cb57806340c23cc1146106d457806346ca626b146106fb5780634af43955146107035780635654d75a14610725575f5ffd5b806331e658a51461063f57806332f0e8c01461069257806334df03ed1461069c578063351fee46146106c3575f5ffd5b806314b406cb116103af5780631e4c72921161037f5780631e4c72921461059b5780631ffb51aa146105ae57806321d0ee70146105ed578063259982e514610619578063270401cb1461062c575f5ffd5b806314b406cb14610523578063150e89cb1461054657806317de3c7e1461057f578063194a4e7e14610592575f5ffd5b80630d7a94f6116103f55780630d7a94f6146104b25780630ed56ffe146104e057806311b288ad146104e857806313560cac146104fd57806313af403514610510575f5ffd5b806286692f146104255780630200737f1461046957806303d60c01146104815780630b33acd61461049f575b5f5ffd5b61044c7f00000000000000000000000000000000000012517b53a1de5c4092c90dc458c281565b6040516001600160a01b0390911681526020015b60405180910390f35b6104736250df2081565b604051908152602001610460565b61048c620d89e51981565b60405160029190910b8152602001610460565b61044c6104ad36600461817d565b610e4f565b6104c56104c036600461824c565b6110df565b60408051938452602084019290925290820152606001610460565b610473607881565b6104fb6104f6366004618276565b611407565b005b61044c61050b3660046182ad565b61170d565b6104fb61051e3660046182c4565b611735565b6105366105313660046182c4565b611818565b6040519015158152602001610460565b61056d7f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff9091168152602001610460565b6104fb61058d3660046182c4565b6118cc565b61047360045481565b6104736b0295be96e64066972000000081565b6105d57f000000000000000000000000000000000000000000000c0a16dff6cf7ecc29dd81565b6040516001600160801b039091168152602001610460565b6106006105fb366004618305565b611aaa565b6040516001600160e01b03199091168152602001610460565b610600610627366004618305565b611b0b565b6104fb61063a366004618276565b611b62565b61065261064d3660046182c4565b611d40565b6040805197885260208801969096529486019390935260608501919091526080840152151560a08301526001600160a01b031660c082015260e001610460565b61048c620d89e681565b6105d57f000000000000000000000000000000000000000000000c0a16dff6cf7ecc2a0d81565b6104fb611f5d565b61047361151881565b61044c7f00000000000000000000000000000000000049487bf4f1b2f91b71ab49a5168181565b61048c600a81565b6105366107113660046182c4565b60086020525f908152604090205460ff1681565b61074d6107333660046182ad565b60096020525f90815260409020546001600160401b031681565b6040516001600160401b039091168152602001610460565b61077861077336600461838b565b61211e565b604080516001600160e01b03199094168452602084019290925262ffffff1690820152606001610460565b6104736107b13660046182c4565b60076020525f908152604090205481565b6104736aa56fa5b99019a5c800000081565b600254610473565b6107ef6107ea3660046183e4565b612189565b604080516001600160e01b03199093168352602083019190915201610460565b61060061081d36600461847c565b6121f3565b6104fb6108303660046182c4565b612254565b61044c7f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c281565b61048c7f00000000000000000000000000000000000000000000000000000000000300c081565b6104736201fa4081565b610473600c5481565b6108a96108a43660046182c4565b612624565b6040516104609190618528565b600d5461044c906001600160a01b031681565b6104736108d73660046182c4565b60036020525f908152604090205481565b6104736b033b2e3c9fd0803ce800000081565b61090e610909366004618536565b612710565b60405161046091906185a2565b6104736109293660046182c4565b60016020525f908152604090205481565b61048c7f000000000000000000000000000000000000000000000000000000000002946e81565b6104736109c481565b61097d6109783660046185b4565b6129a0565b604080516001600160e01b03199093168352600f9190910b602083015201610460565b610a326109ae3660046182ad565b5f6020819052908152604090208054600182015460028301546003909301546001600160a01b0392831693928216926001600160401b03600160a01b90930483169281169161ffff680100000000000000008304811692600160501b81049091169160ff600160601b830416916001600160801b03600160681b9091048116911689565b604080516001600160a01b039a8b1681529990981660208a01526001600160401b039687169789019790975294909316606087015261ffff91821660808701521660a0850152151560c08401526001600160801b0390811660e08401521661010082015261012001610460565b6104fb612a09565b610600610ab5366004618634565b612bb4565b610473610ac83660046182c4565b60056020525f908152604090205481565b610473606481565b610473600b5481565b610b24610af83660046182c4565b600a6020525f90815260409020546001600160a01b03811690600160a01b90046001600160401b031682565b604080516001600160a01b0390931683526001600160401b03909116602083015201610460565b6104fb610b5936600461868d565b612c17565b610c45604080516101c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915250604080516101c08101825260018082525f60208301819052928201819052606082018390526080820183905260a0820183905260c0820181905260e0820181905261010082018390526101208201839052610140820181905261016082015261018081018290526101a081019190915290565b60405161046091906186ad565b610c5b61271081565b60405162ffffff9091168152602001610460565b61044c7f0000000000000000000000000000000000000000000df9a07bfe6e582d998c3c81565b610ca9610ca436600461824c565b612d37565b60408051928352602083019190915201610460565b610cd1610ccc3660046182c4565b612f8f565b604080519615158752600295860b60208801529390940b928501929092526001600160a01b0390811660608501521660808301526001600160801b031660a082015260c001610460565b61044c7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095181565b610600610d503660046187ce565b61315c565b6104fb610d63366004618276565b6131b1565b6104736a108b2a2c2802909400000081565b61044c610d883660046182c4565b6001600160a01b039081165f9081526001602081815260408084205484529083905290912001541690565b61047361a8c081565b6104fb610dca3660046182c4565b6133d3565b6104737f0000000000000000000000000000000000000000000000007e3b7bceacf4000081565b610473610e043660046182c4565b60066020525f908152604090205481565b6104fb610e233660046182c4565b6135cd565b61044c7f000000000000000000000000000000000000000000037e48e91ea6c20d0f7cd881565b5f600e54600114610e945760405162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b60448201526064015b60405180910390fd5b6002600e558915801590610ea9575060408a11155b610ede5760405162461bcd60e51b8152600401610e8b906020808252600490820152636e616d6560e01b604082015260600190565b8715801590610eee5750600c8811155b610f235760405162461bcd60e51b81526020600482015260066024820152651cde5b589bdb60d21b6044820152606401610e8b565b612000861115610f755760405162461bcd60e51b815260206004820152601060248201527f6d6574616461746120746f6f20626967000000000000000000000000000000006044820152606401610e8b565b610f818b8b8b8b613754565b8a8a8a8a604051610f91906180fd565b610f9e949392919061883d565b604051809103905ff080158015610fb7573d5f5f3e3d5ffd5b509050610fe1816001600160a01b03871615610fd35786610fd5565b335b8d8d8d8d8d8d8a613816565b8315610ff057610ff0846139d1565b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03166348c89491600161102a84612624565b3388886040516020016110409493929190618863565b60408051601f198184030181529082905261105e9291602001618896565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161108991906185a2565b5f604051808303815f875af11580156110a4573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110cb9190810190618943565b506001600e559a9950505050505050505050565b6001600160a01b038083165f81815260016020908152604080832054808452918390528220805492948594859490911614801561112457506001600160a01b03871615155b801561113c57506002810154600160601b900460ff16155b6111775760405162461bcd60e51b815260206004820152600c60248201526b6e6f74206f6e20637572766560a01b6044820152606401610e8b565b6001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c28116908816105f816111d2577f000000000000000000000000000000000000000000000c0a16dff6cf7ecc2a0d6111f4565b7f000000000000000000000000000000000000000000000c0a16dff6cf7ecc29dd5b90505f82611222577f00000000000000000000000000000000000012517b53a1de5c4092c90dc458c2611244565b7f0000000000000000000000000000000000000000000df9a07bfe6e582d998c3c5b90505f61125085613b6c565b61125b9060646189d0565b90505f6112688786613bed565b90505f856112825761127d8483876001613cf2565b61128f565b61128f8285876001613db3565b90505f6112a8826127106112a387826189e3565b613dff565b905061271084828f116112bb578e6112bd565b825b6112c791906189f6565b6112d19190618a21565b9a5050505f898c6112e291906189e3565b90505f811161131e5760405162461bcd60e51b8152602060048201526008602482015267647573742062757960c01b6044820152606401610e8b565b5f61132c8387848a15613e2f565b90508661134d57846001600160a01b0316816001600160a01b031610611363565b846001600160a01b0316816001600160a01b0316115b156113d2575f876113805761137b8685896001613cf2565b61138d565b61138d8487896001613db3565b9050808c8f61139c91906189e3565b6113a691906189e3565b9a50876113be576113b98685895f613db3565b6113ca565b6113ca8487895f613cf2565b9c50506113f7565b866113e8576113e38184885f613db3565b6113f4565b6113f48382885f613cf2565b9b505b5050505050505050509250925092565b600d546001600160a01b0316331461144d5760405162461bcd60e51b81526020600482015260096024820152683737ba1037bbb732b960b91b6044820152606401610e8b565b6001600160a01b038083165f818152600160209081526040808320548352908290529020805490921614801561148b57506001600160a01b03831615155b6114c65760405162461bcd60e51b815260206004820152600c60248201526b3ab735b737bbb71031b7b4b760a11b6044820152606401610e8b565b6001600160a01b0382166115085760405162461bcd60e51b81526020600482015260096024820152683d32b9379030b2323960b91b6044820152606401610e8b565b600d546001600160a01b03908116908316036115665760405162461bcd60e51b815260206004820152601860248201527f6f776e65722063616e6e6f742073656c662074617267657400000000000000006044820152606401610e8b565b6001600160a01b0383165f9081526008602052604090205460ff16156115c55760405162461bcd60e51b8152602060048201526014602482015273199959481c9958da5c1a595b9d081b1bd8dad95960621b6044820152606401610e8b565b6001600160a01b038084165f90815260066020908152604080832054600186015490941683526007909152902054818111156115ff578091505b61160c6201fa40836189d0565b42101561165b5760405162461bcd60e51b815260206004820152601060248201527f646576207374696c6c20616374697665000000000000000000000000000000006044820152606401610e8b565b6040805180820182526001600160a01b03868116808352426001600160401b0381811660208087019182528c86165f818152600a9092529790209551865491519086166001600160e01b031990921691909117600160a01b919092160217909355600187015490939116917f2b48fa66fa59891c177a3aa6794eb810cabb3dc101e68326a9df277002f7386a906116f59061a8c0906189d0565b60405190815260200160405180910390a45050505050565b6002818154811061171c575f80fd5b5f918252602090912001546001600160a01b0316905081565b600d546001600160a01b0316331461177b5760405162461bcd60e51b81526020600482015260096024820152683737ba1037bbb732b960b91b6044820152606401610e8b565b6001600160a01b0381166117bd5760405162461bcd60e51b81526020600482015260096024820152683d32b9379030b2323960b91b6044820152606401610e8b565b600d546040516001600160a01b038084169216907fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c905f90a3600d80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038082165f818152600160209081526040808320548352908290528120805491939092911614801561185957506001600160a01b03831615155b6118945760405162461bcd60e51b815260206004820152600c60248201526b3ab735b737bbb71031b7b4b760a11b6044820152606401610e8b565b600281015468010000000000000000900461ffff16158015906118c557506002810154600160501b900461ffff1615155b9392505050565b600e5460011461190b5760405162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b6044820152606401610e8b565b6002600e556001600160a01b038082165f818152600160209081526040808320548352908290529020805490921614801561194e57506001600160a01b03821615155b6119895760405162461bcd60e51b815260206004820152600c60248201526b3ab735b737bbb71031b7b4b760a11b6044820152606401610e8b565b6002810154600160601b900460ff166119d45760405162461bcd60e51b815260206004820152600d60248201526c1b9bdd0819dc98591d585d1959609a1b6044820152606401610e8b565b604080516001600160a01b0384811660208301527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116916348c89491916003910160408051601f1981840301815290829052611a339291602001618896565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401611a5e91906185a2565b5f604051808303815f875af1158015611a79573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611aa09190810190618943565b50506001600e5550565b5f336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511614611af45760405163570c108560e11b815260040160405180910390fd5b611b018686868686613e7d565b9695505050505050565b5f336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511614611b555760405163570c108560e11b815260040160405180910390fd5b611b018686868686613e97565b6001600160a01b038083165f8181526001602090815260408083205483529082905290208054909216148015611ba057506001600160a01b03831615155b611bdb5760405162461bcd60e51b815260206004820152600c60248201526b3ab735b737bbb71031b7b4b760a11b6044820152606401610e8b565b60018101546001600160a01b03163314611c2b5760405162461bcd60e51b81526020600482015260116024820152701b9bdd08199959481c9958da5c1a595b9d607a1b6044820152606401610e8b565b6001600160a01b038216611c6d5760405162461bcd60e51b81526020600482015260096024820152683d32b9379030b2323960b91b6044820152606401610e8b565b6001600160a01b0383165f9081526008602052604090205460ff1615611ccc5760405162461bcd60e51b8152602060048201526014602482015273199959481c9958da5c1a595b9d081b1bd8dad95960621b6044820152606401610e8b565b6001600160a01b038084165f8181526006602052604080822042905560018501549051868516949190911692917ff1dbd322e431f00d83a6dbf85d09896187639f7dd04d0a0baeaf298d7e2c4ec591a460010180546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b038082165f8181526001602090815260408083205480845291839052822080549294859485948594859485948594929391929116148015611d9057506001600160a01b038a1615155b611dcb5760405162461bcd60e51b815260206004820152600c60248201526b3ab735b737bbb71031b7b4b760a11b6044820152606401610e8b565b5f611dff6001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511684613f1c565b50505090507f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26001600160a01b03168b6001600160a01b03161015611e7c57611e75611e61826001600160a01b0316670de0b6b3a7640000600160601b613fce565b826001600160a01b0316600160601b613fce565b9950611eb6565b611eb3611e9f600160601b670de0b6b3a7640000846001600160a01b0316613fce565b600160601b836001600160a01b0316613fce565b99505b611ec48a633b9aca006189f6565b60038301546002840154919a506001600160801b039081169950600160681b9091041696506b0295be96e640669720000000611f02886127106189f6565b611f0c9190618a21565b6002830154909650600160601b900460ff16945084611f2b575f611f4d565b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409515b9350505050919395979092949650565b600e54600114611f9c5760405162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b6044820152606401610e8b565b6002600e55335f9081526003602052604090205480611ff05760405162461bcd60e51b815260206004820152601060248201526f6e6f7468696e6720746f20636c61696d60801b6044820152606401610e8b565b335f818152600360209081526040808320839055600782529182902042905581519081019290925281018290526001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116906348c894919060029060600160408051601f19818403018152908290526120729291602001618896565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161209d91906185a2565b5f604051808303815f875af11580156120b8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526120df9190810190618943565b5060405181815233907fd046302bdc39599e60a5981e59227dcd1c643f512f56f2e984390c3ac6eadedb906020015b60405180910390a2506001600e55565b5f8080336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951161461216a5760405163570c108560e11b815260040160405180910390fd5b612177888888888861406a565b9250925092505b955095509592505050565b5f80336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116146121d45760405163570c108560e11b815260040160405180910390fd5b6121e389898989898989614936565b9150915097509795505050505050565b5f336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951161461223d5760405163570c108560e11b815260040160405180910390fd5b61224985858585613e7d565b90505b949350505050565b600d546001600160a01b0316331461229a5760405162461bcd60e51b81526020600482015260096024820152683737ba1037bbb732b960b91b6044820152606401610e8b565b6001600160a01b038082165f81815260016020908152604080832054835290829052902080549092161480156122d857506001600160a01b03821615155b6123135760405162461bcd60e51b815260206004820152600c60248201526b3ab735b737bbb71031b7b4b760a11b6044820152606401610e8b565b6001600160a01b038281165f908152600a6020908152604091829020825180840190935254928316808352600160a01b9093046001600160401b0316908201529061238e5760405162461bcd60e51b815260206004820152600b60248201526a1b9bc81c1c9bdc1bdcd85b60aa1b6044820152606401610e8b565b61a8c081602001516001600160401b03166123a991906189d0565b4210156123f85760405162461bcd60e51b815260206004820152601060248201527f7665746f2077696e646f77206f70656e000000000000000000000000000000006044820152606401610e8b565b6001600160a01b0383165f9081526008602052604090205460ff16156124575760405162461bcd60e51b8152602060048201526014602482015273199959481c9958da5c1a595b9d081b1bd8dad95960621b6044820152606401610e8b565b80602001516001600160401b031660065f856001600160a01b03166001600160a01b031681526020019081526020015f2054106124d65760405162461bcd60e51b815260206004820152601160248201527f7665746f65643a206465762061637465640000000000000000000000000000006044820152606401610e8b565b60208082015160018401546001600160a01b03165f90815260079092526040909120546001600160401b03909116116125515760405162461bcd60e51b815260206004820152601360248201527f7665746f65643a2064657620636c61696d6564000000000000000000000000006044820152606401610e8b565b6001600160a01b038084165f818152600a6020908152604080832080546001600160e01b03191690556006909152808220429055845160018701549151908516949190911692917ff1dbd322e431f00d83a6dbf85d09896187639f7dd04d0a0baeaf298d7e2c4ec591a4805160018301546040516001600160a01b0392831692918216918616907f80d218b3e568f93e9263f90b2f5520e641e3a29704ad2d002df5022ddd08bcc7905f90a45160019190910180546001600160a01b0319166001600160a01b0390921691909117905550565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f5f7f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26001600160a01b0316846001600160a01b0316106126b0577f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c2846126d3565b837f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c25b6040805160a0810182526001600160a01b0393841681529290911660208301526280000090820152600a6060820152306080820152949350505050565b6060336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951161461275b5760405163570c108560e11b815260040160405180910390fd5b5f8061276984860186618a40565b915091508160ff166001036127ad575f5f5f5f848060200190518101906127909190618ae7565b93509350935093506127a484848484614951565b50505050612986565b8160ff16600203612920575f5f828060200190518101906127ce9190618b8f565b604051637a94c56560e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c260248201526044810182905291935091507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063f5298aca906064015f604051808303815f87803b15801561285e575f5ffd5b505af1158015612870573d5f5f3e3d5ffd5b5050604051630b0d9c0960e01b81526001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c2811660048301528581166024830152604482018590527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951169250630b0d9c0991506064015f604051808303815f87803b158015612903575f5ffd5b505af1158015612915573d5f5f3e3d5ffd5b505050505050612986565b8160ff16600303612951575f818060200190518101906129409190618bbb565b905061294b81614d7e565b50612986565b60405162461bcd60e51b815260206004820152600a6024820152693130b21030b1ba34b7b760b11b6044820152606401610e8b565b60405180602001604052805f815250925050505b92915050565b5f80336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116146129eb5760405163570c108560e11b815260040160405180910390fd5b6129f98888888888886152c2565b915091505b965096945050505050565b600e54600114612a485760405162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b6044820152606401610e8b565b6002600e55335f9081526005602052604090205480612a9c5760405162461bcd60e51b815260206004820152601060248201526f6e6f7468696e6720746f20636c61696d60801b6044820152606401610e8b565b335f8181526005602090815260408083209290925581519081019290925281018290526001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116906348c894919060029060600160408051601f1981840301815290829052612b149291602001618896565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401612b3f91906185a2565b5f604051808303815f875af1158015612b5a573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612b819190810190618943565b5060405181815233907f358fe4192934d3bf28ae181feda1f4bd08ca67f5e2fad55582cce5eb67304ae99060200161210e565b5f336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511614612bfe5760405163570c108560e11b815260040160405180910390fd5b612c0c878787878787613e7d565b979650505050505050565b600d546001600160a01b03163314612c5d5760405162461bcd60e51b81526020600482015260096024820152683737ba1037bbb732b960b91b6044820152606401610e8b565b6109c4821115612c9f5760405162461bcd60e51b815260206004820152600d60248201526c0e0cac2d640e8dede40d0d2ced609b1b6044820152606401610e8b565b6078811115612cf05760405162461bcd60e51b815260206004820152600f60248201527f77696e646f7720746f6f206c6f6e6700000000000000000000000000000000006044820152606401610e8b565b600b829055600c81905560408051838152602081018390527fb8a527ef7e40c1958efe96ee873a7a1ed40d699d073c1809907b7477e780788e910160405180910390a15050565b6001600160a01b038083165f81815260016020908152604080832054808452918390528220805492948594929391929116148015612d7d57506001600160a01b03861615155b8015612d9557506002810154600160601b900460ff16155b612dd05760405162461bcd60e51b815260206004820152600c60248201526b6e6f74206f6e20637572766560a01b6044820152606401610e8b565b5f8511612e0d5760405162461bcd60e51b815260206004820152600b60248201526a1e995c9bc8185b5bdd5b9d60aa1b6044820152606401610e8b565b6001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c28116908716105f81612e68577f000000000000000000000000000000000000000000000c0a16dff6cf7ecc2a0d612e8a565b7f000000000000000000000000000000000000000000000c0a16dff6cf7ecc29dd5b90505f82612eb8577f00000000000000000000000000000000000049487bf4f1b2f91b71ab49a51681612eda565b7f000000000000000000000000000000000000000000037e48e91ea6c20d0f7cd85b90505f612ee78685613bed565b90505f612ef682858c88613e2f565b905084612f1757826001600160a01b0316816001600160a01b031611612f2d565b826001600160a01b0316816001600160a01b0316105b15612f355750815b5f85612f4c57612f478383875f613cf2565b612f58565b612f588284875f613db3565b9050612710612f686064836189f6565b612f729190618a21565b9850612f7e89826189e3565b995050505050505050509250929050565b6001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c28116908216105f808080808561300f577f000000000000000000000000000000000000000000000000000000000002946e7f00000000000000000000000000000000000000000000000000000000000300c0613061565b6130387f00000000000000000000000000000000000000000000000000000000000300c0618bd6565b6130617f000000000000000000000000000000000000000000000000000000000002946e618bd6565b909550935085613091577f00000000000000000000000000000000000049487bf4f1b2f91b71ab49a516816130b3565b7f000000000000000000000000000000000000000000037e48e91ea6c20d0f7cd85b9250856130e0577f00000000000000000000000000000000000012517b53a1de5c4092c90dc458c2613102565b7f0000000000000000000000000000000000000000000df9a07bfe6e582d998c3c5b91508561312f577f000000000000000000000000000000000000000000000c0a16dff6cf7ecc2a0d613151565b7f000000000000000000000000000000000000000000000c0a16dff6cf7ecc29dd5b905091939550919395565b5f336001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116146131a65760405163570c108560e11b815260040160405180910390fd5b61224c8484846154bb565b6001600160a01b038083165f81815260016020908152604080832054835290829052902080549092161480156131ef57506001600160a01b03831615155b61322a5760405162461bcd60e51b815260206004820152600c60248201526b3ab735b737bbb71031b7b4b760a11b6044820152606401610e8b565b60018101546001600160a01b0316331461327a5760405162461bcd60e51b81526020600482015260116024820152701b9bdd08199959481c9958da5c1a595b9d607a1b6044820152606401610e8b565b6001600160a01b0382166132bc5760405162461bcd60e51b81526020600482015260096024820152683d32b9379030b2323960b91b6044820152606401610e8b565b6001600160a01b0383165f9081526008602052604090205460ff16156133155760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481b1bd8dad95960921b6044820152606401610e8b565b6001600160a01b038084165f8181526006602052604080822042905560018501549051868516949190911692917ff1dbd322e431f00d83a6dbf85d09896187639f7dd04d0a0baeaf298d7e2c4ec591a4600181810180546001600160a01b0319166001600160a01b038581169182179092559085165f81815260086020526040808220805460ff19169095179094559251919290917f2eebc77280e803c1584a99dec9756d1920992ee7daee56f7748bba55833b03fb9190a3505050565b600d546001600160a01b031633146134195760405162461bcd60e51b81526020600482015260096024820152683737ba1037bbb732b960b91b6044820152606401610e8b565b600e546001146134585760405162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b6044820152606401610e8b565b6002600e55600454806134ad5760405162461bcd60e51b815260206004820152601360248201527f6e6f7468696e6720746f207769746864726177000000000000000000000000006044820152606401610e8b565b5f600455604080516001600160a01b038481166020830152818301849052825180830384018152606083019093527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116916348c894919161351391600291608001618896565b6040516020818303038152906040526040518263ffffffff1660e01b815260040161353e91906185a2565b5f604051808303815f875af1158015613559573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526135809190810190618943565b50816001600160a01b03167ffc7ad544ff6a06d6499925723d25b6fe70457a42939995b1d3d6f560fe336333826040516135bc91815260200190565b60405180910390a250506001600e55565b6001600160a01b038082165f818152600160209081526040808320548352908290529020805490921614801561360b57506001600160a01b03821615155b6136465760405162461bcd60e51b815260206004820152600c60248201526b3ab735b737bbb71031b7b4b760a11b6044820152606401610e8b565b60018101546001600160a01b031633146136965760405162461bcd60e51b81526020600482015260116024820152701b9bdd08199959481c9958da5c1a595b9d607a1b6044820152606401610e8b565b6001600160a01b0382165f9081526008602052604090205460ff16156136ef5760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481b1bd8dad95960921b6044820152606401610e8b565b6001600160a01b038083165f818152600860209081526040808320805460ff1916600190811790915560069092528083204290559085015490519316927f2eebc77280e803c1584a99dec9756d1920992ee7daee56f7748bba55833b03fb9190a35050565b5f61376185858585615505565b5f818152600960205260409020549091506001600160401b031680158061379c57506137986115186001600160401b0383166189d0565b4210155b6137e85760405162461bcd60e51b815260206004820152601460248201527f6e616d652b7469636b657220636f6f6c646f776e0000000000000000000000006044820152606401610e8b565b505f908152600960205260409020805467ffffffffffffffff1916426001600160401b031617905550505050565b5f6138228a8a846155b4565b9050336138308260a0902090565b8b6001600160a01b03167f147cf8a6eba4eb1d3c8de618b1be305a7a92952aad35754ceb08809243e8ebfb8c8c8c8c8c8c8c6040516138759796959493929190618bf6565b60405180910390a4816138b6576040516001600160a01b038b16907f730e9a1c8323f5b0250ba19c45b4f07c7224b2cee6a61feefe75471226b3f4e1905f90a25b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316636276cbbe827f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26001600160a01b03168d6001600160a01b031610613945577f00000000000000000000000000000000000049487bf4f1b2f91b71ab49a51681613967565b7f000000000000000000000000000000000000000000037e48e91ea6c20d0f7cd85b6040518363ffffffff1660e01b8152600401613984929190618c4e565b6020604051808303815f875af11580156139a0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139c49190618c72565b5050505050505050505050565b6040516370a0823160e01b81523060048201525f907f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26001600160a01b0316906370a0823190602401602060405180830381865afa158015613a35573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a599190618c8d565b9050613a877f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c23330856158b3565b6040516370a0823160e01b8152306004820152829082906001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c216906370a0823190602401602060405180830381865afa158015613aed573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b119190618c8d565b613b1b91906189e3565b14613b685760405162461bcd60e51b815260206004820152601560248201527f666565206f6e207472616e736665722071756f746500000000000000000000006044820152606401610e8b565b5050565b60028101545f90600160501b900461ffff16808203613b8d57505f92915050565b60028301545f90613ba7906001600160401b0316426189e3565b9050818110613bb957505f9392505050565b81613bc482826189e3565b6002860154613be3919068010000000000000000900461ffff166189f6565b61224c9190618a21565b5f613c216001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511684613f1c565b509192505082159050613c90577f000000000000000000000000000000000000000000037e48e91ea6c20d0f7cd86001600160a01b0316816001600160a01b03161015613c8b57507f000000000000000000000000000000000000000000037e48e91ea6c20d0f7cd85b61299a565b7f00000000000000000000000000000000000049487bf4f1b2f91b71ab49a516816001600160a01b0316816001600160a01b0316111561299a57507f00000000000000000000000000000000000049487bf4f1b2f91b71ab49a5168192915050565b5f836001600160a01b0316856001600160a01b03161115613d11579293925b6001600160a01b038516613d2b5762bfc9215f526004601cfd5b6fffffffffffffffffffffffffffffffff60601b606084901b166001600160a01b038686031683613d8757866001600160a01b0316613d748383896001600160a01b0316613fce565b81613d8157613d81618a0d565b04612c0c565b612c0c613d9e8383896001600160a01b0316613dff565b886001600160a01b0316808204910615150190565b5f6001600160a01b038481169086160360ff81901d90810118600160601b6001600160801b038516613de6818484613fce565b9350845f83858409111684019350505050949350505050565b5f613e0b848484613fce565b90508180613e1b57613e1b618a0d565b838509156118c557600101806118c5575f5ffd5b5f6001600160801b038416156001600160a01b038616151715613e5957634f2461b85f526004601cfd5b81613e7057613e6b85858560016159d2565b612249565b6122498585856001615abd565b5f604051630a85dc2960e01b815260040160405180910390fd5b5f8080613eb3613eac36899003890189618ca4565b60a0902090565b815260208101919091526040015f2060020154600160601b900460ff16613f0a5760405162461bcd60e51b815260206004820152600b60248201526a637572766520706861736560a81b6044820152606401610e8b565b5063259982e560e01b95945050505050565b5f5f5f5f5f613f2a86615ba8565b604051631e2eaeaf60e01b8152600481018290529091505f906001600160a01b03891690631e2eaeaf90602401602060405180830381865afa158015613f72573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f969190618c8d565b90506001600160a01b03811695508060a01c60020b945062ffffff8160b81c16935062ffffff8160d01c169250505092959194509250565b5f838302815f1985870982811083820303915050808411613fed575f5ffd5b805f03613fff575082900490506118c5565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b5f808080614080613eac368a90038a018a618ca4565b5f818152602081905260409020600281015491925090600160601b900460ff16156140bd57506315d7892d60e21b93505f925082915061217e9050565b60ff5f5c16156140fc5760405162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b6044820152606401610e8b565b60015f805c60ff19168217905d505f8060015d505f8060025d506001810154600160a01b90046001600160401b031643116141795760405162461bcd60e51b815260206004820152601860248201527f74726164696e67206f70656e73206e65787420626c6f636b00000000000000006044820152606401610e8b565b5f6001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c2166141b160208c018c6182c4565b6001600160a01b0316141590505f816141cd60208c018c618d1e565b1515141590505f816141df575f6141e8565b6141e884613b6c565b6141f39060646189d0565b90505f82156143655784545f906142159088906001600160a01b031632615be4565b90505f6a108b2a2c2802909400000082101561424557614240826a108b2a2c280290940000006189e3565b614247565b5f5b90505f811161428d5760405162461bcd60e51b81526020600482015260126024820152710eec2d8d8cae840c6c2e07440644a40dac2f60731b6044820152606401610e8b565b5f8e602001351215614319575f6142a689888488615c95565b90505f81116142ec5760405162461bcd60e51b81526020600482015260126024820152710eec2d8d8cae840c6c2e07440644a40dac2f60731b6044820152606401610e8b565b5f8f602001356142fb90618d39565b9050818111156143125761430f82826189e3565b94505b5050614362565b808e6020013511156143625760405162461bcd60e51b81526020600482015260126024820152710eec2d8d8cae840c6c2e07440644a40dac2f60731b6044820152606401610e8b565b50505b5f60208d01351283151503614918575f816143838e60200135615f4a565b61438d91906189e3565b90508315614471575f856143f6576143f17f00000000000000000000000000000000000012517b53a1de5c4092c90dc458c26143c98a89613bed565b7f000000000000000000000000000000000000000000000c0a16dff6cf7ecc2a0d6001613cf2565b61444c565b61444c6144038988613bed565b7f0000000000000000000000000000000000000000000df9a07bfe6e582d998c3c7f000000000000000000000000000000000000000000000c0a16dff6cf7ecc29dd6001613db3565b90505f614460826127106112a388826189e3565b90508083111561446e578092505b50505b5f61271061447f85846189f6565b6144899190618a21565b9050801561453c57604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018290527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b15801561451c575f5ffd5b505af115801561452e573d5f5f3e3d5ffd5b5050505061453c8782615f61565b82156148d5575f61454d8e8e615fd1565b90506001600160a01b0381161561467357604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018590527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b1580156145e9575f5ffd5b505af11580156145fb573d5f5f3e3d5ffd5b505050506001600160a01b0381165f90815260056020526040812080548692906146269084906189d0565b909155505087546040518581526001600160a01b038381169216907ff22acaaca393d16ec4a7adae1e62c7e14a9d01e52f9f140fc030e03f73638f649060200160405180910390a36148d3565b6040516370a0823160e01b81526001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409518116600483015285917f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c2909116906370a0823190602401602060405180830381865afa1580156146fb573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061471f9190618c8d565b106147cc57604051630b0d9c0960e01b81526001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c281166004830152326024830152604482018690527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511690630b0d9c09906064015f604051808303815f87803b1580156147b1575f5ffd5b505af11580156147c3573d5f5f3e3d5ffd5b505050506148d3565b604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018590527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b158015614857575f5ffd5b505af1158015614869573d5f5f3e3d5ffd5b5050325f908152600560205260408120805488945090925061488c9084906189d0565b9091555050875460405185815232916001600160a01b0316907ff22acaaca393d16ec4a7adae1e62c7e14a9d01e52f9f140fc030e03f73638f649060200160405180910390a35b505b808060015d50828060025d505f6148ec84836189d0565b90508015614914576315d7892d60e21b9b5060801b99505f985061217e975050505050505050565b5050505b506315d7892d60e21b9d5f9d508d9c509a5050505050505050505050565b5f5f604051630a85dc2960e01b815260040160405180910390fd5b60a084205f818152602081905260408120805490916001600160a01b03918216917f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c21682109080826149e4577f000000000000000000000000000000000000000000000000000000000002946e7f00000000000000000000000000000000000000000000000000000000000300c0614a36565b614a0d7f00000000000000000000000000000000000000000000000000000000000300c0618bd6565b614a367f000000000000000000000000000000000000000000000000000000000002946e618bd6565b915091505f7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316635a6bcfda8c60405180608001604052808760020b81526020018660020b815260200188614ab3577f000000000000000000000000000000000000000000000c0a16dff6cf7ecc2a0d614ad5565b7f000000000000000000000000000000000000000000000c0a16dff6cf7ecc29dd5b6001600160801b031681525f6020909101526040516001600160e01b031960e085901b168152614b09929190600401618d53565b60408051808303815f875af1158015614b24573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614b489190618da4565b5090505f84614b6057614b5b82600f0b90565b614b6a565b614b6a8260801d90565b614b7390618dc6565b6001600160801b031690507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b031663a584119486614bbc578d60200151614bbf565b8d515b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526024015f604051808303815f87803b158015614bfd575f5ffd5b505af1158015614c0f573d5f5f3e3d5ffd5b505060405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095181166004830152602482018590528916925063a9059cbb91506044016020604051808303815f875af1158015614c7f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614ca39190618deb565b614cda5760405162461bcd60e51b81526020600482015260086024820152673a3930b739b332b960c11b6044820152606401610e8b565b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03166311da60b46040518163ffffffff1660e01b81526004016020604051808303815f875af1158015614d37573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614d5b9190618c8d565b508915614d7057614d708c88878e8e8e615ff7565b505050505050505050505050565b5f614d8882612624565b90505f5f5f614d988460a0902090565b81526020019081526020015f2090505f7f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26001600160a01b0316846001600160a01b03161090505f7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316635a6bcfda856040518060800160405280620d89e51960020b8152602001620d89e660020b81526020015f81526020015f5f1b8152506040518363ffffffff1660e01b8152600401614e5d929190618d53565b60408051808303815f875af1158015614e78573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614e9c9190618da4565b5090505f82614eb457614eaf8260801d90565b614ebe565b614ebe82600f0b90565b6001600160801b031690505f83614ede57614ed983600f0b90565b614ee8565b614ee88360801d90565b6001600160801b031690505f600a614f018460036189f6565b614f0b9190618a21565b9050821561500957604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018490527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b158015614f9e575f5ffd5b505af1158015614fb0573d5f5f3e3d5ffd5b505050508083614fc091906189e3565b60018701546001600160a01b03165f9081526003602052604081208054909190614feb9084906189d0565b925050819055508060045f82825461500391906189d0565b90915550505b5f600a6150178460036189f6565b6150219190618a21565b90508215615248577f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316630b0d9c098761506757896020015161506a565b89515b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018690526064015f604051808303815f87803b1580156150b5575f5ffd5b505af11580156150c7573d5f5f3e3d5ffd5b505050505f81846150d891906189e3565b111561519d5760018701546001600160a01b03808b169163a9059cbb911661510084876189e3565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015615148573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061516c9190618deb565b61519d5760405162461bcd60e51b8152602060048201526002602482015261743160f01b6044820152606401610e8b565b801561524857600d5460405163a9059cbb60e01b81526001600160a01b03918216600482015260248101839052908a169063a9059cbb906044016020604051808303815f875af11580156151f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906152179190618deb565b6152485760405162461bcd60e51b81526020600482015260026024820152613a1960f11b6044820152606401610e8b565b60018701546001600160a01b03908116908a167fda4fc92b8716c8bb1183b17b10a2b9d5f86158e6ca54ccc2f8512bfa3113d62d61528685886189e3565b61529085886189e3565b6040805192835260208301919091528101869052606081018590526080015b60405180910390a3505050505050505050565b5f80806152d7613eac368a90038a018a618ca4565b5f8181526020818152604082209293506001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c2169061531e908c018c6182c4565b6001600160a01b03161415905081600201600c9054906101000a900460ff16156153655763b47b2fb160e01b6153598b84848d8d8d8d6164e6565b945094505050506129fe565b5f6153738385848d8d61659a565b905081151561538560208c018c618d1e565b1515146154a2575f6153c06001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511686613f1c565b505050905082615405577f00000000000000000000000000000000000012517b53a1de5c4092c90dc458c26001600160a01b0316816001600160a01b0316111561543c565b7f0000000000000000000000000000000000000000000df9a07bfe6e582d998c3c6001600160a01b0316816001600160a01b031610155b156154a0576250df205a10156154945760405162461bcd60e51b815260206004820152601d60248201527f67726164756174696f6e20627579206e65656473206d6f7265206761730000006044820152606401610e8b565b6154a08c858786616945565b505b63b47b2fb160e01b9c909b509950505050505050505050565b60405162461bcd60e51b815260206004820152601d60248201527f706d61763a20706f6f6c73206f6e6c792076696120637265617465282900000060448201525f90606401610e8b565b5f61554485858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061748292505050565b61558284848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061748292505050565b604080516020810193909352820152606001604051602081830303815290604052805190602001209050949350505050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091526155e784612624565b90505f6155f58260a0902090565b9050604051806101200160405280866001600160a01b03168152602001856001600160a01b03168152602001436001600160401b03168152602001426001600160401b031681526020018461564a575f61564e565b600b545b61ffff16815260200184615662575f615666565b600c545b61ffff1681526020015f151581526020015f6001600160801b031681526020015f6001600160801b03168152505f5f8381526020019081526020015f205f820151815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160401b0302191690836001600160401b031602179055506060820151816002015f6101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160020160086101000a81548161ffff021916908361ffff16021790555060a082015181600201600a6101000a81548161ffff021916908361ffff16021790555060c082015181600201600c6101000a81548160ff02191690831515021790555060e082015181600201600d6101000a8154816001600160801b0302191690836001600160801b03160217905550610100820151816003015f6101000a8154816001600160801b0302191690836001600160801b031602179055509050508060015f876001600160a01b03166001600160a01b031681526020019081526020015f2081905550600285908060018154018082558091505060019003905f5260205f20015f9091909190916101000a8154816001600160a01b0302191690836001600160a01b031602179055504260065f876001600160a01b03166001600160a01b031681526020019081526020015f2081905550509392505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291515f928392908816916159169190618e06565b5f604051808303815f865af19150503d805f811461594f576040519150601f19603f3d011682016040523d82523d5f602084013e615954565b606091505b509150915081801561597e57508051158061597e57508080602001905181019061597e9190618deb565b6159ca5760405162461bcd60e51b815260206004820152601960248201527f71756f7465207472616e7366657246726f6d206661696c6564000000000000006044820152606401610e8b565b505050505050565b5f8115615a42575f6001600160a01b03841115615a0657615a0184600160601b876001600160801b0316613fce565b615a1d565b615a1d6001600160801b038616606086901b618a21565b9050615a3a615a35826001600160a01b0389166189d0565b617570565b91505061224c565b5f6001600160a01b03841115615a6f57615a6a84600160601b876001600160801b0316613dff565b615a8c565b615a8c606085901b6001600160801b038716808204910615150190565b9050806001600160a01b03871611615aab57634323a5555f526004601cfd5b6001600160a01b03861603905061224c565b5f825f03615acc57508361224c565b6fffffffffffffffffffffffffffffffff60601b606085901b168215615b67576001600160a01b03861684810290858281615b0957615b09618a0d565b0403615b3957818101828110615b3757615b2d83896001600160a01b031683613dff565b935050505061224c565b505b50615a3a8185615b526001600160a01b038a1683618a21565b615b5c91906189d0565b808204910615150190565b6001600160a01b038616848102908582041481831116615b8e5763f5c787f15f526004601cfd5b808203615b2d615a35846001600160a01b038b1684613dff565b6040515f90615bc7908390600690602001918252602082015260400190565b604051602081830303815290604052805190602001209050919050565b5f5f615bf08584617596565b90505f615bfd8685617610565b9050815c5f818103615c7b576040516370a0823160e01b81526001600160a01b0387811660048301528816906370a0823190602401602060405180830381865afa158015615c4d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190615c719190618c8d565b905080835d615c7f565b50815c5b615c8982826189d0565b98975050505050505050565b5f5f615ca18686613bed565b90505f85615ccf577f00000000000000000000000000000000000012517b53a1de5c4092c90dc458c2615cf1565b7f0000000000000000000000000000000000000000000df9a07bfe6e582d998c3c5b90505f86615d1f577f000000000000000000000000000000000000000000000c0a16dff6cf7ecc2a0d615d41565b7f000000000000000000000000000000000000000000000c0a16dff6cf7ecc29dd5b90505f5f8815615e0257836001600160a01b0316856001600160a01b031610615d71575f9550505050505061224c565b6fffffffffffffffffffffffffffffffff60601b606084901b165f615d9f6001600160a01b0388168b6189f6565b82811015935090508583615dec575f615dcb846001600160a01b038b16615dc686836189e3565b613fce565b9050876001600160a01b03168110615de65760019450615dea565b8091505b505b615df888828887613db3565b9450505050615ead565b836001600160a01b0316856001600160a01b031611615e28575f9550505050505061224c565b5f615e4189600160601b866001600160801b0316613fce565b9050856001600160a01b031681101580615e785750846001600160a01b031681876001600160a01b0316615e7591906189e3565b11155b91505f82615e9857615e93826001600160a01b0389166189e3565b615e9a565b855b9050615ea881888786613cf2565b935050505b815f03615ec1575f9550505050505061224c565b8015615ee457615ed8826127106112a38a826189e3565b9550505050505061224c565b615ef582612710615dc68a826189e3565b95505b5f86118015615f26575081612710615f1089896189f6565b615f1a9190618a21565b615f2490886189e3565b115b15615f3d5785615f3581618e1c565b965050615ef8565b5050505050949350505050565b5f5f8212615f58578161299a565b61299a82618d39565b5f600a615f6f8360036189f6565b615f799190618a21565b90508060045f828254615f8c91906189d0565b90915550615f9c905081836189e3565b60018401546001600160a01b03165f9081526003602052604081208054909190615fc79084906189d0565b9091555050505050565b5f60208214615fe157505f61299a565b615fee60205f8486618e31565b6118c591618e58565b60a086205f61600587613b6c565b6160109060646189d0565b9050835f8061602c858a6a108b2a2c2802909400000087615c95565b9050808311156160465761604081846189e3565b91508092505b505f61271061605585856189f6565b61605f9190618a21565b90505f61606c82856189e3565b90505f81116160a85760405162461bcd60e51b8152602060048201526008602482015267647573742062757960c01b6044820152606401610e8b565b5f6160b48d8c8461766c565b9050878110156160f15760405162461bcd60e51b8152602060048201526008602482015267736c69707061676560c01b6044820152606401610e8b565b6a108b2a2c2802909400000081111561613c5760405162461bcd60e51b815260206004820152600d60248201526c18d85c081a5b9d985c9a585b9d609a1b6044820152606401610e8b565b604051632961046560e21b81526001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c2811660048301527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951169063a5841194906024015f604051808303815f87803b1580156161bc575f5ffd5b505af11580156161ce573d5f5f3e3d5ffd5b505050506162287f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c27f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951858561622391906189d0565b617795565b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03166311da60b46040518163ffffffff1660e01b81526004016020604051808303815f875af1158015616285573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906162a99190618c8d565b50604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018490527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b158015616335575f5ffd5b505af1158015616347573d5f5f3e3d5ffd5b505050506163558c84615f61565b6163608732836178ab565b808c600201600d8282829054906101000a90046001600160801b03166163869190618e75565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550818c6003015f8282829054906101000a90046001600160801b03166163cf9190618e75565b92506101000a8154816001600160801b0302191690836001600160801b031602179055507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316630b0d9c098c616431578e60200151616434565b8e515b6040516001600160e01b031960e084901b1681526001600160a01b039182166004820152908d166024820152604481018490526064015f604051808303815f87803b158015616481575f5ffd5b505af1158015616493573d5f5f3e3d5ffd5b505050506164a68c8860018886866178c6565b83156164d7576164d77f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c28b86617795565b50505050505050505050505050565b5f806164fa613eac368b90038b018b618ca4565b90505f87151561650d6020890189618d1e565b1515141590505f61653d8961652b576165268860801d90565b616535565b61653588600f0b90565b600f0b615f4a565b90505f61655c8a6165525761652689600f0b90565b6165358960801d90565b9050821561657d576165788c8b835f8d60200135128b8b617994565b955090505b61658b8b85858586866178c6565b50505050979650505050505050565b5f5f6165b8856165ae576165268460801d90565b61653584600f0b90565b90505f6165d7866165cd5761652685600f0b90565b6165358560801d90565b90505f8615156165ea6020880188618d1e565b1515141590505f602087013581138203616607575060015c6166f9565b5f82616613575f61661c565b61661c8b613b6c565b6166279060646189d0565b905061271061663682876189f6565b6166409190618a21565b915081156166f757604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018390527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b1580156166d3575f5ffd5b505af11580156166e5573d5f5f3e3d5ffd5b505050506166f38b83615f61565b8195505b505b811561676c5761670a8932856178ab565b89546a108b2a2c280290940000009061672e908b906001600160a01b031632615be4565b111561676c5760405162461bcd60e51b815260206004820152600d60248201526c18d85c081a5b9d985c9a585b9d609a1b6044820152606401610e8b565b5f60ff19815c16815d50811561681457828a600201600d8282829054906101000a90046001600160801b03166167a29190618e75565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550838a6003015f8282829054906101000a90046001600160801b03166167eb9190618e75565b92506101000a8154816001600160801b0302191690836001600160801b031602179055506168f4565b60028a0154839085906001600160801b03808416600160681b909204161161683c575f61685c565b60028c015461685c908390600160681b90046001600160801b0316618e94565b60028d0180547fffffff00000000000000000000000000000000ffffffffffffffffffffffffff16600160681b6001600160801b039384160217905560038d01548282169116116168ad575f6168c6565b60038c01546168c69082906001600160801b0316618e94565b60038d0180546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905550505b6169388a8a8485616905578761690f565b61690f85896189d0565b8661693057858911616921575f616932565b61692b868a6189e3565b616932565b885b886178c6565b5050505095945050505050565b6002830180546cff0000000000000000000000001916600160601b1790555f8161698f577f00000000000000000000000000000000000012517b53a1de5c4092c90dc458c26169b1565b7f0000000000000000000000000000000000000000000df9a07bfe6e582d998c3c5b90505f5f83616a01577f000000000000000000000000000000000000000000000000000000000002946e7f00000000000000000000000000000000000000000000000000000000000300c0616a53565b616a2a7f00000000000000000000000000000000000000000000000000000000000300c0618bd6565b616a537f000000000000000000000000000000000000000000000000000000000002946e618bd6565b915091505f5f5f7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316635a6bcfda8b60405180608001604052808960020b81526020018860020b81526020018b616ad2577f000000000000000000000000000000000000000000000c0a16dff6cf7ecc2a0d616af4565b7f000000000000000000000000000000000000000000000c0a16dff6cf7ecc29dd5b6001600160801b0316616b0690618d39565b81525f6020909101526040516001600160e01b031960e085901b168152616b31929190600401618f35565b60408051808303815f875af1158015616b4c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190616b709190618da4565b50905086616b8757616b828160801d90565b616b91565b616b9181600f0b90565b6001600160801b0316925086616bb057616bab81600f0b90565b616bba565b616bba8160801d90565b6001600160801b031691505f9050616bfb6001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511689613f1c565b505050905086616c1f57856001600160a01b0316816001600160a01b031610616c35565b856001600160a01b0316816001600160a01b0316115b15616cf0577f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b031663f3cd914c8b60405180606001604052808b151581526020015f1981526020018a6001600160a01b03168152506040518363ffffffff1660e01b8152600401616cae929190618f3f565b6020604051808303815f875af1158015616cca573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190616cee9190618c8d565b505b50604051635275965160e01b81526001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511690635275965190616d41908c9061271090600401618f89565b5f604051808303815f87803b158015616d58575f5ffd5b505af1158015616d6a573d5f5f3e3d5ffd5b505050505f5f87616daf57616daa877f000000000000000000000000fff6fbe64b68d618d47c209fe40b0d8ee6e23c91616da56001886189e3565b617b22565b616de4565b616de47f000000000000000000000000000000000000000000000000000000010009046c88616ddf6001886189e3565b617b8c565b90505f88616e2c57616e277f000000000000000000000000000000000000000000000000000000010009046c89616ddf60016aa56fa5b99019a5c80000006189e3565b616e67565b616e67887f000000000000000000000000fff6fbe64b68d618d47c209fe40b0d8ee6e23c91616da560016aa56fa5b99019a5c80000006189e3565b9050806001600160801b0316826001600160801b031610616e885780616e8a565b815b60408051608081018252620d89e5198152620d89e660208201526001600160801b038316818301525f606082018190529151632d35e7ed60e11b81529295509093506001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951169250635a6bcfda91616f0c918f91600401618f35565b60408051808303815f875af1158015616f27573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190616f4b9190618da4565b5090505f88616f6357616f5e8260801d90565b616f6d565b616f6d82600f0b90565b616f7690618dc6565b6001600160801b031690505f89616f9657616f9183600f0b90565b616fa0565b616fa08360801d90565b616fa990618dc6565b6001600160801b031690505f8a616fd2578d6020016020810190616fcd91906182c4565b616fdf565b616fdf60208f018f6182c4565b9050858211156171c657604051632961046560e21b81526001600160a01b0382811660048301527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951169063a5841194906024015f604051808303815f87803b158015617049575f5ffd5b505af115801561705b573d5f5f3e3d5ffd5b50508e546001600160a01b0316915063a9059cbb90507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095161709c89866189e3565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af11580156170e4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906171089190618deb565b61713f5760405162461bcd60e51b81526020600482015260086024820152673a3930b739b332b960c11b6044820152606401610e8b565b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03166311da60b46040518163ffffffff1660e01b81526004016020604051808303815f875af115801561719c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906171c09190618c8d565b5061726e565b8186111561726e576001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e4095116630b0d9c098261dead61720b868b6189e3565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064015f604051808303815f87803b158015617257575f5ffd5b505af1158015617269573d5f5f3e3d5ffd5b505050505b5f61727984896189e3565b9050801561733957604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018290527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b15801561730c575f5ffd5b505af115801561731e573d5f5f3e3d5ffd5b505050508060045f82825461733391906189d0565b90915550505b8d546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa15801561737e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906173a29190618c8d565b9050801561741f578e5460405163a9059cbb60e01b815261dead6004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303815f875af11580156173f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061741d9190618deb565b505b8e546040518f916001600160a01b0316907f38b20cb5110bddd584591f48d073b7c2fd750721141e9b7f0b67dd0856ed44f9906174689089908990918252602082015260400190565b60405180910390a350505050505050505050505050505050565b5f805b825181101561756357604160f81b8382815181106174a5576174a5618fa9565b01602001516001600160f81b031916108015906174e65750605a60f81b8382815181106174d4576174d4618fa9565b01602001516001600160f81b03191611155b1561755b578281815181106174fd576174fd618fa9565b602001015160f81c60f81b60f81c60206175179190618fbd565b60f81b83828151811061752c5761752c618fa9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505b600101617485565b5050805160209091012090565b806001600160a01b0381168114617591576175916393dafdf160e01b617bc8565b919050565b5f82826040516020016175f29291906060808252600f908201527f706d61762e6361702e626f756768740000000000000000000000000000000000608082015260208101929092526001600160a01b0316604082015260a00190565b60405160208183030381529060405280519060200120905092915050565b5f82826040516020016175f29291906060808252600e908201527f706d61762e6361702e7374617274000000000000000000000000000000000000608082015260208101929092526001600160a01b0316604082015260a00190565b5f5f7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b031663f3cd914c866040518060600160405280881515158152602001876176bc90618d39565b8152602001886176db576176d66401000276a36001618fd6565b6176fa565b6176fa600173fffd8963efd1fc6a506488495d951d5263988d26618ff5565b6001600160a01b03168152506040518363ffffffff1660e01b8152600401617723929190619014565b6020604051808303815f875af115801561773f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906177639190618c8d565b9050836177795761777481600f0b90565b617783565b6177838160801d90565b6001600160801b031695945050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291515f928392908716916177f09190618e06565b5f604051808303815f865af19150503d805f8114617829576040519150601f19603f3d011682016040523d82523d5f602084013e61782e565b606091505b50915091508180156178585750805115806178585750808060200190518101906178589190618deb565b6178a45760405162461bcd60e51b815260206004820152601560248201527f71756f7465207472616e73666572206661696c656400000000000000000000006044820152606401610e8b565b5050505050565b5f6178b68484617596565b9050805c828101825d5050505050565b5f6178fa6001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511687613f1c565b5050885460028a015460038b0154604080518b15158152602081018b9052908101899052606081018890526001600160a01b038087166080830152600160681b9093046001600160801b0390811660a083015290911660c08201529394503293911691507f4f5b0649704c895561ce323139857abb735dc20c54845fde1bc14b74e853a2d69060e00160405180910390a350505050505050565b5f80806179a9613eac368b90038b018b618ca4565b5f818152602081905260408120549192506001600160a01b03909116906179d1838332615be4565b90506a108b2a2c280290940000008110617a225760405162461bcd60e51b81526020600482015260126024820152710eec2d8d8cae840c6c2e07440644a40dac2f60731b6044820152606401610e8b565b878015617a4257506a108b2a2c28029094000000617a408a836189d0565b115b15617aad575f6a108b2a2c28029094000000617a5e8b846189d0565b617a6891906189e3565b9050617a898432617a84856a108b2a2c280290940000006189e3565b6178ab565b617a968c8c838b8b617bd0565b617aa0818b6189e3565b955093506129fe92505050565b6a108b2a2c28029094000000617ac38a836189d0565b1115617b065760405162461bcd60e51b81526020600482015260126024820152710eec2d8d8cae840c6c2e07440644a40dac2f60731b6044820152606401610e8b565b617b1183328b6178ab565b5096995f9950975050505050505050565b5f826001600160a01b0316846001600160a01b03161115617b41579192915b5f617b63856001600160a01b0316856001600160a01b0316600160601b613fce565b9050617b83617b7e84838888036001600160a01b0316613fce565b6180dc565b95945050505050565b5f826001600160a01b0316846001600160a01b03161115617bab579192915b61224c617b7e83600160601b8787036001600160a01b0316613fce565b805f5260045ffd5b5f8080617be5613eac368a90038a018a618ca4565b81526020019081526020015f205f015f9054906101000a90046001600160a01b031690505f7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b031663f3cd914c8860405180606001604052808a1515815260200189617c5790618d39565b81526020018a617c8557617c80600173fffd8963efd1fc6a506488495d951d5263988d26618ff5565b617c95565b617c956401000276a36001618fd6565b6001600160a01b03168152506040518363ffffffff1660e01b8152600401617cbe929190618f3f565b6020604051808303815f875af1158015617cda573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190617cfe9190618c8d565b90505f86617d1557617d108260801d90565b617d1f565b617d1f82600f0b90565b6001600160801b03169050805f03617d39575050506178a4565b5f617d448686615fd1565b90506001600160a01b03811615617e7657604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018390527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b158015617de0575f5ffd5b505af1158015617df2573d5f5f3e3d5ffd5b505050506001600160a01b0381165f9081526005602052604081208054849290617e1d9084906189d0565b92505081905550806001600160a01b0316846001600160a01b03167ff22acaaca393d16ec4a7adae1e62c7e14a9d01e52f9f140fc030e03f73638f6484604051617e6991815260200190565b60405180910390a36180d1565b6040516370a0823160e01b81526001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409518116600483015283917f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c2909116906370a0823190602401602060405180830381865afa158015617efe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190617f229190618c8d565b10617fcf57604051630b0d9c0960e01b81526001600160a01b037f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c281166004830152326024830152604482018490527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409511690630b0d9c09906064015f604051808303815f87803b158015617fb4575f5ffd5b505af1158015617fc6573d5f5f3e3d5ffd5b505050506180d1565b604051630ab714fb60e11b81523060048201527f0000000000000000000000004ea005168d7f09a7a0ba9d1def21a479950e44c26024820152604481018390527f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03169063156e29f6906064015f604051808303815f87803b15801561805a575f5ffd5b505af115801561806c573d5f5f3e3d5ffd5b5050325f908152600560205260408120805486945090925061808f9084906189d0565b909155505060405182815232906001600160a01b038616907ff22acaaca393d16ec4a7adae1e62c7e14a9d01e52f9f140fc030e03f73638f64906020016152af565b505050505050505050565b806001600160801b0381168114617591576175916393dafdf160e01b617bc8565b6108a18061901f83390190565b5f5f83601f84011261811a575f5ffd5b5081356001600160401b03811115618130575f5ffd5b602083019150836020828501011115618147575f5ffd5b9250929050565b6001600160a01b0381168114618162575f5ffd5b50565b8015158114618162575f5ffd5b803561759181618165565b5f5f5f5f5f5f5f5f5f5f60e08b8d031215618196575f5ffd5b8a356001600160401b038111156181ab575f5ffd5b6181b78d828e0161810a565b909b5099505060208b01356001600160401b038111156181d5575f5ffd5b6181e18d828e0161810a565b90995097505060408b01356001600160401b038111156181ff575f5ffd5b61820b8d828e0161810a565b90975095505060608b013561821f8161814e565b935060808b0135925060a08b0135915061823b60c08c01618172565b90509295989b9194979a5092959850565b5f5f6040838503121561825d575f5ffd5b82356182688161814e565b946020939093013593505050565b5f5f60408385031215618287575f5ffd5b82356182928161814e565b915060208301356182a28161814e565b809150509250929050565b5f602082840312156182bd575f5ffd5b5035919050565b5f602082840312156182d4575f5ffd5b81356118c58161814e565b5f60a082840312156182ef575f5ffd5b50919050565b5f608082840312156182ef575f5ffd5b5f5f5f5f5f610160868803121561831a575f5ffd5b85356183258161814e565b945061833487602088016182df565b93506183438760c088016182f5565b92506101408601356001600160401b0381111561835e575f5ffd5b61836a8882890161810a565b969995985093965092949392505050565b5f606082840312156182ef575f5ffd5b5f5f5f5f5f61014086880312156183a0575f5ffd5b85356183ab8161814e565b94506183ba87602088016182df565b93506183c98760c0880161837b565b92506101208601356001600160401b0381111561835e575f5ffd5b5f5f5f5f5f5f5f6101a0888a0312156183fb575f5ffd5b87356184068161814e565b96506184158960208a016182df565b95506184248960c08a016182f5565b9450610140880135935061016088013592506101808801356001600160401b0381111561844f575f5ffd5b61845b8a828b0161810a565b989b979a50959850939692959293505050565b8060020b8114618162575f5ffd5b5f5f5f5f6101008587031215618490575f5ffd5b843561849b8161814e565b93506184aa86602087016182df565b925060c08501356184ba8161814e565b915060e08501356184ca8161846e565b939692955090935050565b6001600160a01b0381511682526001600160a01b03602082015116602083015262ffffff6040820151166040830152606081015160020b60608301526001600160a01b0360808201511660808301525050565b60a0810161299a82846184d5565b5f5f60208385031215618547575f5ffd5b82356001600160401b0381111561855c575f5ffd5b6185688582860161810a565b90969095509350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6118c56020830184618574565b5f5f5f5f5f5f61016087890312156185ca575f5ffd5b86356185d58161814e565b95506185e488602089016182df565b94506185f38860c0890161837b565b935061012087013592506101408701356001600160401b03811115618616575f5ffd5b61862289828a0161810a565b979a9699509497509295939492505050565b5f5f5f5f5f5f610120878903121561864a575f5ffd5b86356186558161814e565b955061866488602089016182df565b945060c0870135935060e087013592506101008701356001600160401b03811115618616575f5ffd5b5f5f6040838503121561869e575f5ffd5b50508035926020909101359150565b8151151581526101c0810160208301516186cb602084018215159052565b5060408301516186df604084018215159052565b5060608301516186f3606084018215159052565b506080830151618707608084018215159052565b5060a083015161871b60a084018215159052565b5060c083015161872f60c084018215159052565b5060e083015161874360e084018215159052565b5061010083015161875961010084018215159052565b5061012083015161876f61012084018215159052565b5061014083015161878561014084018215159052565b5061016083015161879b61016084018215159052565b506101808301516187b161018084018215159052565b506101a08301516187c76101a084018215159052565b5092915050565b5f5f5f60e084860312156187e0575f5ffd5b83356187eb8161814e565b92506187fa85602086016182df565b915060c084013561880a8161814e565b809150509250925092565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f618850604083018688618815565b8281036020840152612c0c818587618815565b610100810161887282876184d5565b6001600160a01b03851660a08301528360c08301528260e083015295945050505050565b60ff83168152604060208201525f61224c6040830184618574565b634e487b7160e01b5f52604160045260245ffd5b60405160a081016001600160401b03811182821017156188e7576188e76188b1565b60405290565b604051601f8201601f191681016001600160401b0381118282101715618915576189156188b1565b604052919050565b5f6001600160401b03821115618935576189356188b1565b50601f01601f191660200190565b5f60208284031215618953575f5ffd5b81516001600160401b03811115618968575f5ffd5b8201601f81018413618978575f5ffd5b805161898b6189868261891d565b6188ed565b81815285602083850101111561899f575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561299a5761299a6189bc565b8181038181111561299a5761299a6189bc565b808202811582820484141761299a5761299a6189bc565b634e487b7160e01b5f52601260045260245ffd5b5f82618a3b57634e487b7160e01b5f52601260045260245ffd5b500490565b5f5f60408385031215618a51575f5ffd5b823560ff81168114618a61575f5ffd5b915060208301356001600160401b03811115618a7b575f5ffd5b8301601f81018513618a8b575f5ffd5b8035618a996189868261891d565b818152866020838501011115618aad575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b62ffffff81168114618162575f5ffd5b80516175918161814e565b5f5f5f5f848603610100811215618afc575f5ffd5b60a0811215618b09575f5ffd5b50618b126188c5565b8551618b1d8161814e565b81526020860151618b2d8161814e565b60208201526040860151618b4081618acc565b60408201526060860151618b538161846e565b60608201526080860151618b668161814e565b60808201529350618b7960a08601618adc565b60c086015160e090960151949790965092505050565b5f5f60408385031215618ba0575f5ffd5b8251618bab8161814e565b6020939093015192949293505050565b5f60208284031215618bcb575f5ffd5b81516118c58161814e565b5f8160020b627fffff198103618bee57618bee6189bc565b5f0392915050565b6001600160a01b0388168152608060208201525f618c1860808301888a618815565b8281036040840152618c2b818789618815565b90508281036060840152618c40818587618815565b9a9950505050505050505050565b60c08101618c5c82856184d5565b6001600160a01b03831660a08301529392505050565b5f60208284031215618c82575f5ffd5b81516118c58161846e565b5f60208284031215618c9d575f5ffd5b5051919050565b5f60a0828403128015618cb5575f5ffd5b50618cbe6188c5565b8235618cc98161814e565b81526020830135618cd98161814e565b60208201526040830135618cec81618acc565b60408201526060830135618cff8161846e565b60608201526080830135618d128161814e565b60808201529392505050565b5f60208284031215618d2e575f5ffd5b81356118c581618165565b5f600160ff1b8201618d4d57618d4d6189bc565b505f0390565b618d5d81846184d5565b8151600290810b60a08301526020830151900b60c0820152604082015160e0820152606082015161010082015261014061012082018190525f908201526101600192915050565b5f5f60408385031215618db5575f5ffd5b505080516020909101519092909150565b5f81600f0b6f7fffffffffffffffffffffffffffffff198103618bee57618bee6189bc565b5f60208284031215618dfb575f5ffd5b81516118c581618165565b5f82518060208501845e5f920191825250919050565b5f81618e2a57618e2a6189bc565b505f190190565b5f5f85851115618e3f575f5ffd5b83861115618e4b575f5ffd5b5050820193919092039150565b8035602083101561299a575f19602084900360031b1b1692915050565b6001600160801b03818116838216019081111561299a5761299a6189bc565b6001600160801b03828116828216039081111561299a5761299a6189bc565b8035618ebe8161814e565b6001600160a01b031682526020810135618ed78161814e565b6001600160a01b031660208301526040810135618ef381618acc565b62ffffff1660408301526060810135618f0b8161846e565b60020b60608301526080810135618f218161814e565b6001600160a01b0381166080840152505050565b618d5d8184618eb3565b618f498184618eb3565b8151151560a0820152602082015160c082015260408201516001600160a01b031660e082015261012061010082018190525f908201526101400192915050565b60c08101618f978285618eb3565b62ffffff831660a08301529392505050565b634e487b7160e01b5f52603260045260245ffd5b60ff818116838216019081111561299a5761299a6189bc565b6001600160a01b03818116838216019081111561299a5761299a6189bc565b6001600160a01b03828116828216039081111561299a5761299a6189bc565b618f4981846184d556fe608060405234801561000f575f5ffd5b506040516108a13803806108a183398101604081905261002e9161013d565b5f6100398382610226565b5060016100468282610226565b50335f8181526002602090815260408083206b033b2e3c9fd0803ce80000009081905590519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350506102e0565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126100c3575f5ffd5b81516001600160401b038111156100dc576100dc6100a0565b604051601f8201601f19908116603f011681016001600160401b038111828210171561010a5761010a6100a0565b604052818152838201602001851015610121575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b5f5f6040838503121561014e575f5ffd5b82516001600160401b03811115610163575f5ffd5b61016f858286016100b4565b602085015190935090506001600160401b0381111561018c575f5ffd5b610198858286016100b4565b9150509250929050565b600181811c908216806101b657607f821691505b6020821081036101d457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561022157805f5260205f20601f840160051c810160208510156101ff5750805b601f840160051c820191505b8181101561021e575f815560010161020b565b50505b505050565b81516001600160401b0381111561023f5761023f6100a0565b6102538161024d84546101a2565b846101da565b6020601f821160018114610285575f831561026e5750848201515b5f19600385901b1c1916600184901b17845561021e565b5f84815260208120601f198516915b828110156102b45787850151825560209485019460019092019101610294565b50848210156102d157868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b6105b4806102ed5f395ff3fe608060405234801561000f575f5ffd5b5060043610610090575f3560e01c8063313ce56711610063578063313ce5671461010957806370a082311461012357806395d89b4114610142578063a9059cbb1461014a578063dd62ed3e1461015d575f5ffd5b806306fdde0314610094578063095ea7b3146100b257806318160ddd146100d557806323b872dd146100f6575b5f5ffd5b61009c610187565b6040516100a9919061044a565b60405180910390f35b6100c56100c036600461049a565b610212565b60405190151581526020016100a9565b6100e86b033b2e3c9fd0803ce800000081565b6040519081526020016100a9565b6100c56101043660046104c2565b61027d565b610111601281565b60405160ff90911681526020016100a9565b6100e86101313660046104fc565b60026020525f908152604090205481565b61009c610325565b6100c561015836600461049a565b610332565b6100e861016b366004610515565b600360209081525f928352604080842090915290825290205481565b5f805461019390610546565b80601f01602080910402602001604051908101604052809291908181526020018280546101bf90610546565b801561020a5780601f106101e15761010080835404028352916020019161020a565b820191905f5260205f20905b8154815290600101906020018083116101ed57829003601f168201915b505050505081565b335f8181526003602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061026c9086815260200190565b60405180910390a350600192915050565b6001600160a01b0383165f9081526003602090815260408083203384529091528120545f19811461031157828110156102e95760405162461bcd60e51b8152602060048201526009602482015268616c6c6f77616e636560b81b60448201526064015b60405180910390fd5b6001600160a01b0385165f908152600360209081526040808320338452909152902083820390555b61031c858585610345565b95945050505050565b6001805461019390610546565b5f61033e338484610345565b9392505050565b5f6001600160a01b0383166103865760405162461bcd60e51b81526020600482015260076024820152667a65726f20746f60c81b60448201526064016102e0565b6001600160a01b0384165f90815260026020526040902054828110156103d85760405162461bcd60e51b815260206004820152600760248201526662616c616e636560c81b60448201526064016102e0565b6001600160a01b038086165f8181526002602052604080822087860390559287168082529083902080548701905591517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906104379087815260200190565b60405180910390a3506001949350505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114610495575f5ffd5b919050565b5f5f604083850312156104ab575f5ffd5b6104b48361047f565b946020939093013593505050565b5f5f5f606084860312156104d4575f5ffd5b6104dd8461047f565b92506104eb6020850161047f565b929592945050506040919091013590565b5f6020828403121561050c575f5ffd5b61033e8261047f565b5f5f60408385031215610526575f5ffd5b61052f8361047f565b915061053d6020840161047f565b90509250929050565b600181811c9082168061055a57607f821691505b60208210810361057857634e487b7160e01b5f52602260045260245ffd5b5091905056fea2646970667358221220e5be472a7939f31fce5af650e5df93e0880240c1b5f38e2b9aaf172a65d979ce64736f6c634300081c0033a26469706673582212202ff119245f0b29471abad3522ec7fed7b2c6392ccd70ce5b9207d4315ea592b364736f6c634300081c0033
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| 64.5 cm (25.4 in.) Christmas Shiba Dog Greeter (COSTCOINU) | COSTCOINU | 200,000,000.000000 | — | — |
| Price Club (PriceClub) | PriceClub | 200,000,000.000000 | — | — |
| HOTDOG (HOTDOG) | HOTDOG | 200,000,000.000000 | — | — |
| COSTCO OIL (COSTCOIL) | COSTCOIL | 200,000,000.000000 | — | — |
| Illuminati Pizza (PIZZA) | PIZZA | 200,000,000.000000 | — | — |
| Costco Hotdog (CHUSD) | CHUSD | 200,000,000.000000 | — | — |
| COSTO PIZZA (COSTCOPIZZA) | COSTCOPIZZA | 200,000,000.000000 | — | — |
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x181274…1166ca | 17 days agoWed, 29 Jul 2026 08:58:59 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…e1184f06 [1] 0x000000000000…4bc8cd00 data: 0x000000000000000000…9df3a44b |
| 0xf68d6b…19f169 | 20 days agoSun, 26 Jul 2026 09:36:52 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…e1184f06 [1] 0x000000000000…4bc8cd00 data: 0x000000000000000000…01ce6d56 |
| 0x264121…ed87e8 | 20 days agoSun, 26 Jul 2026 00:42:15 UTC | 0xd04630…dedb | [0] 0x000000000000…ffe577ee data: 0x000000000000000000…902f65c6 |
| 0x2b2ae7…d35d90 | 21 days agoSun, 26 Jul 2026 00:22:59 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…1ca39352 data: 0x000000000000000000…59433ce4 |
| 0xbb7330…08a4bb | 21 days agoSun, 26 Jul 2026 00:22:59 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…c72c11d6 data: 0x000000000000000000…13c01e43 |
| 0x6f9369…6afc35 | 21 days agoSun, 26 Jul 2026 00:22:59 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…32b227ea data: 0x000000000000000000…53626fc6 |
| 0x95290f…dd9675 | 21 days agoSun, 26 Jul 2026 00:22:59 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…426d9641 data: 0x000000000000000000…5fe293d5 |
| 0xb2d8fd…c3acd3 | 21 days agoSat, 25 Jul 2026 18:38:52 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…26ae5ec5 data: 0x000000000000000000…4877fd2c |
| 0x516a1e…34c205 | 21 days agoSat, 25 Jul 2026 18:38:52 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…e6f9eb78 data: 0x000000000000000000…c2beb39e |
| 0x2277f3…3e0de1 | 21 days agoSat, 25 Jul 2026 18:38:52 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…3ea0ff85 data: 0x000000000000000000…7a10d592 |
| 0xdd846c…9a4144 | 21 days agoSat, 25 Jul 2026 18:38:52 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…9ab358b2 data: 0x000000000000000000…ef27b6fe |
| 0x80707a…de0152 | 21 days agoSat, 25 Jul 2026 18:15:14 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…2abc1fe0 data: 0x000000000000000000…3ae18dea |
| 0xdf2e35…aa6b8f | 21 days agoSat, 25 Jul 2026 18:15:14 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…e7ab0dcd data: 0x000000000000000000…dfdad62c |
| 0x16caa2…2b3373 | 21 days agoSat, 25 Jul 2026 18:15:14 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…58532b64 data: 0x000000000000000000…d328bcab |
| 0xc35d16…06d2f8 | 21 days agoSat, 25 Jul 2026 18:15:14 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…f73eec97 data: 0x000000000000000000…7ea0eefe |
| 0x0c1f75…6c2cc2 | 21 days agoSat, 25 Jul 2026 18:15:14 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…c4b799a4 data: 0x000000000000000000…bba4554b |
| 0x4a18e1…ac38a1 | 21 days agoSat, 25 Jul 2026 17:35:38 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…b80d9f26 data: 0x000000000000000000…8a15c531 |
| 0x4c7012…76a44f | 21 days agoSat, 25 Jul 2026 15:26:35 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…89891782 data: 0x000000000000000000…392784cd |
| 0x572be3…bf6129 | 21 days agoSat, 25 Jul 2026 13:23:08 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…f3a44a28 data: 0x000000000000000000…594a451d |
| 0x0bbd5b…a571a4 | 21 days agoSat, 25 Jul 2026 09:57:01 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…7be2b3e4 data: 0x000000000000000000…c6916a93 |
| 0x024154…62fe79 | 21 days agoSat, 25 Jul 2026 09:46:19 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…bb433007 data: 0x000000000000000000…b7f5ac1e |
| 0x753ba0…63fdc1 | 21 days agoSat, 25 Jul 2026 09:46:19 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…9c527a66 data: 0x000000000000000000…4a0224dc |
| 0xc055b6…0e43bf | 21 days agoSat, 25 Jul 2026 08:04:46 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…8568ebde data: 0x000000000000000000…71c4439d |
| 0xae8ca9…d48d6a | 21 days agoSat, 25 Jul 2026 07:52:56 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…e1184f06 [1] 0x000000000000…fcab58ba data: 0x000000000000000000…9df3a44a |
| 0x158b37…27caa7 | 21 days agoSat, 25 Jul 2026 07:33:29 UTC | 0x4f5b06…a2d6 | [0] 0x000000000000…511a20eb [1] 0x000000000000…a9dd3ed5 data: 0x000000000000000000…cda53732 |
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x728e70…39bc6e | claimCreatorFees | 18,644,749 | 21 days agoSat, 25 Jul 2026 02:16:56 UTC | 0x5c02…da59 | IN | PmavHookQuoted | $0.000 ETH | 0.00000929 | |
| 0x18bdbc…da2603 | claimCreatorFees | 18,594,610 | 21 days agoSat, 25 Jul 2026 00:53:03 UTC | 0x5c02…da59 | IN | PmavHookQuoted | $0.000 ETH | 0.00001316 | |
| 0x933823…5cda4b | create | 18,593,965 | 21 days agoSat, 25 Jul 2026 00:51:58 UTC | 0x5c02…da59 | IN | PmavHookQuoted | $0.000 ETH | 0.00008584 | |
| 0x70d84c…916bec | create | 18,585,698 | 21 days agoSat, 25 Jul 2026 00:38:09 UTC | 0x5c02…da59 | IN | PmavHookQuoted | $0.000 ETH | 0.00008560 | |
| 0x639fc6…0a0186 | create | 18,582,166 | 21 days agoSat, 25 Jul 2026 00:32:14 UTC | 0x5c02…da59 | IN | PmavHookQuoted | $0.000 ETH | 0.00008840 | |
| 0xde18db…d8829a | create | 18,577,807 | 22 days agoSat, 25 Jul 2026 00:24:57 UTC | 0x5c02…da59 | IN | PmavHookQuoted | $0.000 ETH | 0.00009428 | |
| 0xc57078…6a815e | lockFeeRecipientTo | 18,577,806 | 22 days agoSat, 25 Jul 2026 00:24:57 UTC | 0xbc47…7a2c | IN | PmavHookQuoted | $0.000 ETH | 0.00000660 | |
| 0x923704…10a395 | create | 18,577,721 | 22 days agoSat, 25 Jul 2026 00:24:48 UTC | 0xbc47…7a2c | IN | PmavHookQuoted | $0.000 ETH | 0.00008696 | |
| 0x1b7849…6c2485 | create | 18,540,578 | 22 days agoFri, 24 Jul 2026 23:22:43 UTC | 0x5c02…da59 | IN | PmavHookQuoted | $0.000 ETH | 0.00008885 | |
| 0x41889a…367ab7 | create | 18,531,562 | 22 days agoFri, 24 Jul 2026 23:07:39 UTC | 0x5c02…da59 | IN | PmavHookQuoted | $0.000 ETH | 0.00009084 |
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x93382309…5cda4b | Transfer | 18,593,965 | 21 days agoSat, 25 Jul 2026 00:51:58 UTC | 0x984d…a8cc | OUT | 0x8366…0951 | 800,000,000.000000 PIZZA | Illuminati Pizza (PIZZA) | |
| 0x93382309…5cda4b | Transfer | 18,593,965 | 21 days agoSat, 25 Jul 2026 00:51:58 UTC | 0x0000…0000 | IN | 0x984d…a8cc | 1,000,000,000.000000 PIZZA | Illuminati Pizza (PIZZA) | |
| 0x70d84cb2…916bec | Transfer | 18,585,698 | 21 days agoSat, 25 Jul 2026 00:38:09 UTC | 0x984d…a8cc | OUT | 0x8366…0951 | 800,000,000.000000 COSTCOPIZZA | COSTO PIZZA (COSTCOPIZZA) | |
| 0x70d84cb2…916bec | Transfer | 18,585,698 | 21 days agoSat, 25 Jul 2026 00:38:09 UTC | 0x0000…0000 | IN | 0x984d…a8cc | 1,000,000,000.000000 COSTCOPIZZA | COSTO PIZZA (COSTCOPIZZA) | |
| 0x639fc610…0a0186 | Transfer | 18,582,166 | 21 days agoSat, 25 Jul 2026 00:32:14 UTC | 0x984d…a8cc | OUT | 0x8366…0951 | 800,000,000.000000 COSTCOIL | COSTCO OIL (COSTCOIL) | |
| 0x639fc610…0a0186 | Transfer | 18,582,166 | 21 days agoSat, 25 Jul 2026 00:32:14 UTC | 0x0000…0000 | IN | 0x984d…a8cc | 1,000,000,000.000000 COSTCOIL | COSTCO OIL (COSTCOIL) | |
| 0xde18db53…d8829a | Transfer | 18,577,807 | 22 days agoSat, 25 Jul 2026 00:24:57 UTC | 0x984d…a8cc | OUT | 0x8366…0951 | 800,000,000.000000 COSTCOINU | 64.5 cm (25.4 in.) Christmas Shiba Dog Greeter (COSTCOINU) | |
| 0xde18db53…d8829a | Transfer | 18,577,807 | 22 days agoSat, 25 Jul 2026 00:24:57 UTC | 0x0000…0000 | IN | 0x984d…a8cc | 1,000,000,000.000000 COSTCOINU | 64.5 cm (25.4 in.) Christmas Shiba Dog Greeter (COSTCOINU) | |
| 0x923704a1…10a395 | Transfer | 18,577,721 | 22 days agoSat, 25 Jul 2026 00:24:48 UTC | 0x984d…a8cc | OUT | 0x8366…0951 | 800,000,000.000000 CHUSD | Costco Hotdog (CHUSD) | |
| 0x923704a1…10a395 | Transfer | 18,577,721 | 22 days agoSat, 25 Jul 2026 00:24:48 UTC | 0x0000…0000 | IN | 0x984d…a8cc | 1,000,000,000.000000 CHUSD | Costco Hotdog (CHUSD) | |
| 0x1b78492d…6c2485 | Transfer | 18,540,578 | 22 days agoFri, 24 Jul 2026 23:22:43 UTC | 0x984d…a8cc | OUT | 0x8366…0951 | 800,000,000.000000 PriceClub | Price Club (PriceClub) | |
| 0x1b78492d…6c2485 | Transfer | 18,540,578 | 22 days agoFri, 24 Jul 2026 23:22:43 UTC | 0x0000…0000 | IN | 0x984d…a8cc | 1,000,000,000.000000 PriceClub | Price Club (PriceClub) | |
| 0x41889a05…367ab7 | Transfer | 18,531,562 | 22 days agoFri, 24 Jul 2026 23:07:39 UTC | 0x984d…a8cc | OUT | 0x8366…0951 | 800,000,000.000000 HOTDOG | HOTDOG (HOTDOG) | |
| 0x41889a05…367ab7 | Transfer | 18,531,562 | 22 days agoFri, 24 Jul 2026 23:07:39 UTC | 0x0000…0000 | IN | 0x984d…a8cc | 1,000,000,000.000000 HOTDOG | HOTDOG (HOTDOG) |
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 18,593,965 | 21 days agoSat, 25 Jul 2026 00:51:58 UTC | 0x933823…5cda4b | CREATE | create | 0x984d…a8cc | OUT | 0x8c25…5bc8 | 0 ETH |
| 18,585,698 | 21 days agoSat, 25 Jul 2026 00:38:09 UTC | 0x70d84c…916bec | CREATE | create | 0x984d…a8cc | OUT | 0x6ee2…59a6 | 0 ETH |
| 18,582,166 | 21 days agoSat, 25 Jul 2026 00:32:14 UTC | 0x639fc6…0a0186 | CREATE | create | 0x984d…a8cc | OUT | 0x167a…3660 | 0 ETH |
| 18,577,807 | 22 days agoSat, 25 Jul 2026 00:24:57 UTC | 0xde18db…d8829a | CREATE | create | 0x984d…a8cc | OUT | 0x48a5…4f06 | 0 ETH |
| 18,577,721 | 22 days agoSat, 25 Jul 2026 00:24:48 UTC | 0x923704…10a395 | CREATE | create | 0x984d…a8cc | OUT | 0x991b…20eb | 0 ETH |
| 18,540,578 | 22 days agoFri, 24 Jul 2026 23:22:43 UTC | 0x1b7849…6c2485 | CREATE | create | 0x984d…a8cc | OUT | 0x4bb3…6a5a | 0 ETH |
| 18,531,562 | 22 days agoFri, 24 Jul 2026 23:07:39 UTC | 0x41889a…367ab7 | CREATE | create | 0x984d…a8cc | OUT | 0x2a85…14fb | 0 ETH |
| 18,517,362 | 22 days agoFri, 24 Jul 2026 22:43:57 UTC | 0xcc99fa…a25569 | CREATE2 | optimized_routeFill921336808 | 0x4e59…956c | IN | 0x984d…a8cc | 0 ETH |