// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {IHooks} from "v4-core/interfaces/IHooks.sol";
import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol";
import {IUnlockCallback} from "v4-core/interfaces/callback/IUnlockCallback.sol";
import {Hooks} from "v4-core/libraries/Hooks.sol";
import {StateLibrary} from "v4-core/libraries/StateLibrary.sol";
import {PoolKey} from "v4-core/types/PoolKey.sol";
import {PoolId, PoolIdLibrary} from "v4-core/types/PoolId.sol";
import {Currency, CurrencyLibrary} from "v4-core/types/Currency.sol";
import {BalanceDelta, BalanceDeltaLibrary} from "v4-core/types/BalanceDelta.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary, toBeforeSwapDelta} from "v4-core/types/BeforeSwapDelta.sol";
import {SwapParams, ModifyLiquidityParams} from "v4-core/types/PoolOperation.sol";
import {HoodlumTickMath} from "./libraries/HoodlumTickMath.sol";
/**
* @title HoodlumPadHook
* @notice The one shared, immutable Uniswap v4 hook every `HoodlumPadFactoryV2` launch attaches
* to its pool. Implements Gate 0 items 3 (batched fee conversion) and 5 (the hook itself).
* Items 7 (payouts in a chosen token) and 8 (optional per-pool transfer tax) were cut from
* V2 v1 post-sweep — see `V2_GATE0_PROPOSAL.md` §12 for the removal record. Item 3's own
* payout claim (always in the launch's own quote asset) is unaffected by that cut.
*
* Trust posture: immutable, no owner, no upgrade, no pause. The only discretionary revert paths
* anywhere in this contract are `beforeInitialize`'s `sender == FACTORY` check and
* `beforeAddLiquidity`'s `liquidityAddLocked[poolId]` check (§12, 2×5 — FACTORY-only, set only
* while a swept curve pool sits empty awaiting its graduated reseed) — no discretionary revert
* path exists in `beforeSwap`/`afterSwap` beyond `PoolManager`'s own insufficient-liquidity case.
* The only mutable per-pool state writable by anyone other than "nobody" is `feeRecipient[poolId]`,
* and its sole writer is `TIMELOCK` (`HoodlumFeeRecipientTimelock`) — see `setFeeRecipient`.
*
* Fee accrual makes zero external calls and never moves a real ERC20 — it is realized as an
* ERC-6909 claim-token credit inside `PoolManager` (`mint(address(this), currencyId, skim)`),
* tracked per pool in `accrued[poolId]`. The only point in this entire pipeline where a real ERC20
* `transfer`/`transferFrom` of the memecoin executes is the batched conversion's own swap-in leg;
* the only point a real transfer of the quote asset executes is the final, separately-callable
* claim functions — never inline inside accrual or conversion. This is what makes every stranding
* vector in Gate 0 §12-D/§3.4 close: a pausable/blacklisting quote token can only ever brick its
* OWN claim, never accrual, never conversion, never the other recipient's claim.
*/
contract HoodlumPadHook is IHooks, IUnlockCallback, ReentrancyGuard {
using SafeERC20 for IERC20;
using StateLibrary for IPoolManager;
using PoolIdLibrary for PoolKey;
using CurrencyLibrary for Currency;
using BalanceDeltaLibrary for BalanceDelta;
// ── fixed protocol addresses ─────────────────────────────────────────────────────────────
IPoolManager public immutable POOL_MANAGER;
/// @notice The only address `beforeInitialize` ever checks against.
address public immutable FACTORY;
address public constant TREASURY = 0x561deB125684F3A6F39414897cC9309658321f4a;
/// @notice The only address that may ever call `setFeeRecipient`.
address public immutable TIMELOCK;
// ── item 3: base fee ─────────────────────────────────────────────────────────────────────
uint256 public constant HOOK_FEE_BPS = 100; // 1%, matches V1's POOL_FEE tier
uint256 public constant CREATOR_SHARE_OF_HOOK_BPS = 5_000;
uint256 public constant PROTOCOL_SHARE_OF_HOOK_BPS = 5_000;
uint256 internal constant BPS_DENOM = 10_000;
uint256 public constant MIN_CONVERT_BPS = 5; // 0.05% of TOTAL_SUPPLY
uint256 public constant MAX_CONVERT_BPS_PER_CALL = 50; // 0.5% of TOTAL_SUPPLY, §12-E
uint256 public constant MAX_CONVERT_STALENESS_SECONDS = 21_600; // 6h
uint256 public constant TOTAL_SUPPLY = 1_000_000_000e18; // every V2 launch mints exactly this
// ── the reused TWAP-minOut guard shape (Gate 0 §3.3) ────────────────────────────────────────
uint32 public constant CONVERT_TWAP_SECONDS = 180;
uint256 public constant CONVERT_SWAP_TOL_BPS = 250; // 2.5%
int24 public constant CONVERT_MAX_TICK_TOTAL = 1_000; // ≈10.5%
uint256 public constant CONVERT_COOLDOWN_SECONDS = 1_800;
// ── item 5: self-hosted oracle (v4 core ships no observe()) ─────────────────────────────────
uint16 public constant HOOK_OBS_CARDINALITY = 200;
struct Observation {
uint32 blockTimestamp;
int56 tickCumulative;
bool initialized;
}
mapping(PoolId => Observation[200]) internal _observations;
mapping(PoolId => uint16) public observationIndex; // last-written slot
mapping(PoolId => uint16) public observationCount; // slots written so far, caps at 200
// ── per-pool registration + ledgers ──────────────────────────────────────────────────────
struct PoolInfo {
bool registered;
address creator; // creatorOf[poolId] — permanent, never rewritten
address feeRecipient; // mutable only via TIMELOCK
address quoteToken;
address memecoinToken;
bool memecoinIsToken0;
uint24 fee;
int24 tickSpacing;
}
mapping(PoolId => PoolInfo) public poolInfo;
mapping(PoolId => uint256) public accrued; // base-fee ledger, memecoin claim-token terms
mapping(PoolId => uint256) public lastConvertAt;
mapping(PoolId => uint256) public pendingTreasuryPayout; // quote-asset terms, claimable by TREASURY
mapping(PoolId => uint256) public pendingQuotePayout; // quote-asset terms, claimable by feeRecipient
/// @notice §12 (2×5): set by FACTORY while a launch's swept curve pool sits empty awaiting its
/// graduated reseed (`gradPhase == SweptAwaitingPool`) — no `PoolManager.modifyLiquidity`
/// add can land against a pool this shallow without letting whoever added it move price
/// for free, so no one, not even FACTORY's eventual reseed mint (unlocked immediately
/// before that call), may add liquidity while this is set.
///
/// MOD-2: the same flag ALSO blocks swaps while set (see `beforeSwap`). A swept pool sits
/// at ZERO liquidity, where a swap fills nothing but walks `slot0` to any tick the caller
/// picks, for gas only — which would let a third party manipulate the reseed's live spot
/// read and DoS the native/token-only reseed via its `ReseedPriceDeviation` guard.
/// Blocking swaps makes the reseed's "this pool's tick cannot have moved since sweep"
/// premise actually hold. FACTORY sets the flag at sweep and clears it on every Phase-B
/// path before any mint, so both locks lift together exactly when the escrow window ends.
mapping(PoolId => bool) public liquidityAddLocked;
// ── item 6/§6.7: abandoned-only liveness signals ────────────────────────────────────────────
mapping(PoolId => uint256) public lastCreatorTouch;
mapping(PoolId => uint256) public lastSwapAt;
/// @notice LOW-MOD-4: the OTHER poolId of the SAME launch — set exactly once, only when a
/// graduation reseed mints a genuinely-new poolId (custom-quote -> WETH conversion
/// success; every other graduation path reuses the curve poolId and never writes this).
/// Bidirectional and permanent. Creator liveness is a LAUNCH-level fact, not a pool-level
/// one: `claimVest` always targets the curve poolId and `pokeAlive` may target either, so
/// a touch on one poolId must reach the launch's live, fee-generating pool. Used solely to
/// route liveness touches to both facets of one launch (see `_touchCreator`).
mapping(PoolId => PoolId) public linkedPoolId;
error UnauthorizedPoolOrigination();
error OnlyPoolManager();
error OnlyTimelock();
error OnlyCreator();
error PoolNotRegistered();
error TwapUnavailable();
error ImpactExceeded();
error CooldownActive(uint256 remaining);
error BelowConvertThreshold();
error ConvertAmountTooLarge();
error ConvertOutputZero();
error ZeroAmount();
error LiquidityAddLocked();
error SwapLockedDuringGraduation();
event PoolRegistered(PoolId indexed poolId, address indexed creator, address quoteToken, bool memecoinIsToken0);
event AccruedMigrated(PoolId indexed fromPoolId, PoolId indexed toPoolId, uint256 amount);
event FeeRecipientChanged(PoolId indexed poolId, address oldRecipient, address newRecipient);
event FeesConverted(PoolId indexed poolId, uint256 memecoinIn, uint256 quoteOut);
event TreasuryPayoutClaimed(PoolId indexed poolId, uint256 amount);
event QuotePayoutClaimed(PoolId indexed poolId, address indexed recipient, uint256 amount);
event CreatorTouched(PoolId indexed poolId, uint256 timestamp);
modifier onlyPoolManager() {
if (msg.sender != address(POOL_MANAGER)) revert OnlyPoolManager();
_;
}
constructor(IPoolManager poolManager_, address factory_, address timelock_) {
POOL_MANAGER = poolManager_;
FACTORY = factory_;
TIMELOCK = timelock_;
}
// ── IHooks: the permission bitmap this address must be mined to match ──────────────────────
function getHookPermissions() public pure returns (Hooks.Permissions memory) {
return Hooks.Permissions({
beforeInitialize: true,
afterInitialize: true,
beforeAddLiquidity: true,
afterAddLiquidity: false,
beforeRemoveLiquidity: false,
afterRemoveLiquidity: false,
beforeSwap: true,
afterSwap: true,
beforeDonate: false,
afterDonate: false,
beforeSwapReturnDelta: true,
afterSwapReturnDelta: true,
afterAddLiquidityReturnDelta: false,
afterRemoveLiquidityReturnDelta: false
});
}
// ── beforeInitialize / afterInitialize (§5.1) ───────────────────────────────────────────────
function beforeInitialize(address sender, PoolKey calldata, uint160) external view onlyPoolManager returns (bytes4) {
if (sender != FACTORY) revert UnauthorizedPoolOrigination();
return IHooks.beforeInitialize.selector;
}
/// @dev Data primed via `primeHookData` is abi-encoded as (address creator, address
/// quoteToken, bool memecoinIsToken0, bool isGraduationReseed, PoolId priorPoolId) — for
/// a graduation reseed (factory calling while the token's `gradPhase ==
/// SweptAwaitingPool`), every field except `quoteToken`/`memecoinIsToken0` (which reflect
/// the NEW pool's own shape — always WETH-normalized or the native-fallback quote — and
/// are therefore taken from the primed data, not copied) is instead read from
/// `priorPoolId`'s already-registered values and copied verbatim, per §12-I — closing the
/// reseed-as-bait-and-switch gap.
function afterInitialize(address sender, PoolKey calldata key, uint160, int24 tick)
external
onlyPoolManager
returns (bytes4)
{
if (sender != FACTORY) revert UnauthorizedPoolOrigination();
PoolId poolId = key.toId();
(address creator, address quoteToken, bool memecoinIsToken0, bool isGraduationReseed, PoolId priorPoolId) =
abi.decode(_hookDataFromInitialize(sender, key), (address, address, bool, bool, PoolId));
address feeRecipient_;
if (isGraduationReseed) {
PoolInfo storage prior = poolInfo[priorPoolId];
if (!prior.registered) revert PoolNotRegistered();
creator = prior.creator;
feeRecipient_ = prior.feeRecipient;
// LOW-MOD-4: carry the creator-liveness history to the new poolId (0 stays 0 — a creator
// who never touched still ages out, preserving the abandoned-only guarantee) and link the
// two poolIds permanently so every FUTURE touch on either lands on both. `creator` is
// copied verbatim (above) and never rewritten, so a creator-authenticated touch on one
// poolId is valid for its twin. Fires at most once per launch (gradPhase latch), only from
// FACTORY (`beforeInitialize` sender-gate), against a pair carrying this launch's unique
// memecoin — so the link can never be overwritten, chained, or collided.
lastCreatorTouch[poolId] = lastCreatorTouch[priorPoolId];
linkedPoolId[poolId] = priorPoolId;
linkedPoolId[priorPoolId] = poolId;
// 3×4 (Gate 1 reopen, 2026-07-25): the convert path abandons priorPoolId at zero
// liquidity forever, which would strand any fee value still in its accrued ledger in
// claim-token form. The claim tokens are denominated in this launch's own memecoin —
// identical on both pools (ERC-6909 ids are currency-scoped, no poolId component) —
// so carrying the LEDGER entry alone re-points that value at the new, liquid pool.
// MOD-2's escrow lock (adds AND swaps dead from sweep until this registration)
// freezes accrued[priorPoolId] for the whole window, so the migrated amount is
// exactly the at-sweep amount, tamper-proof. Fires at most once per launch (the
// gradPhase latch + FACTORY-only origination guarding this whole branch); the
// same-pair native/token-only paths never re-initialize and need no migration —
// their pool keeps its liquidity and its ledger.
uint256 carriedAccrued = accrued[priorPoolId];
if (carriedAccrued != 0) {
accrued[priorPoolId] = 0;
accrued[poolId] = carriedAccrued;
emit AccruedMigrated(priorPoolId, poolId, carriedAccrued);
}
} else {
feeRecipient_ = creator;
}
address memecoinToken =
memecoinIsToken0 ? Currency.unwrap(key.currency0) : Currency.unwrap(key.currency1);
poolInfo[poolId] = PoolInfo({
registered: true,
creator: creator,
feeRecipient: feeRecipient_,
quoteToken: quoteToken,
memecoinToken: memecoinToken,
memecoinIsToken0: memecoinIsToken0,
fee: key.fee,
tickSpacing: key.tickSpacing
});
_observations[poolId][0] = Observation({blockTimestamp: uint32(block.timestamp), tickCumulative: 0, initialized: true});
observationIndex[poolId] = 0;
observationCount[poolId] = 1;
lastSwapAt[poolId] = block.timestamp;
// silence unused-var warning for `tick` (kept in signature to match IHooks exactly)
tick;
emit PoolRegistered(poolId, creator, quoteToken, memecoinIsToken0);
return IHooks.afterInitialize.selector;
}
/// @dev `initialize()` does not forward its own `hookData` argument to `afterInitialize` in
/// v4-core — the factory instead passes it via a side channel this hook exposes only to
/// `FACTORY`, set immediately before calling `PoolManager.initialize()` in the same
/// transaction and cleared immediately after in `afterInitialize`, so it can never be
/// read stale or by an unrelated caller.
bytes internal _pendingHookData;
function primeHookData(bytes calldata hookData_) external {
if (msg.sender != FACTORY) revert UnauthorizedPoolOrigination();
_pendingHookData = hookData_;
}
function _hookDataFromInitialize(address, PoolKey calldata) internal returns (bytes memory data) {
data = _pendingHookData;
delete _pendingHookData;
}
// ── beforeSwap / afterSwap (§5.2): fee skim, self-hosted oracle write ───────────────────────
function beforeSwap(address, PoolKey calldata key, SwapParams calldata params, bytes calldata)
external
onlyPoolManager
returns (bytes4, BeforeSwapDelta, uint24)
{
PoolId poolId = key.toId();
// MOD-2: while a pool is swept-and-awaiting-reseed it holds ZERO liquidity; a swap fills
// nothing but walks slot0 for free. Block it (reuses `liquidityAddLocked`, FACTORY-set at
// sweep and cleared before the reseed mint on every Phase-B path) — this keeps the reseed's
// live spot read manipulation-proof and avoids a spurious `lastSwapAt` bump on a dead pool.
// Checked before any state write so a blocked swap leaves the observation buffer untouched.
if (liquidityAddLocked[poolId]) revert SwapLockedDuringGraduation();
_writeObservation(poolId);
lastSwapAt[poolId] = block.timestamp;
PoolInfo storage info = poolInfo[poolId];
if (!info.registered) return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
bool exactIn = params.amountSpecified < 0;
bool specifiedIsToken0 = params.zeroForOne == exactIn;
bool memecoinIsSpecified = specifiedIsToken0 == info.memecoinIsToken0;
if (!memecoinIsSpecified) return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
uint256 absSpecified = exactIn ? uint256(-params.amountSpecified) : uint256(params.amountSpecified);
uint256 skim = _skimAmount(absSpecified);
if (skim == 0) return (IHooks.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0);
Currency memecoinCurrency = info.memecoinIsToken0 ? key.currency0 : key.currency1;
POOL_MANAGER.mint(address(this), memecoinCurrency.toId(), skim);
accrued[poolId] += skim;
return (IHooks.beforeSwap.selector, toBeforeSwapDelta(int128(int256(skim)), 0), 0);
}
function afterSwap(address, PoolKey calldata key, SwapParams calldata params, BalanceDelta delta, bytes calldata)
external
onlyPoolManager
returns (bytes4, int128)
{
PoolId poolId = key.toId();
PoolInfo storage info = poolInfo[poolId];
if (!info.registered) return (IHooks.afterSwap.selector, 0);
bool exactIn = params.amountSpecified < 0;
bool specifiedIsToken0 = params.zeroForOne == exactIn;
bool memecoinIsSpecified = specifiedIsToken0 == info.memecoinIsToken0;
if (memecoinIsSpecified) return (IHooks.afterSwap.selector, 0);
// memecoin is the unspecified currency here: its realized delta is exactly what `delta`
// reports on that side. A positive delta on the memecoin side means the pool (and
// therefore the trader, net of pool math) is paying memecoin out — a buy; negative means
// memecoin flowed in — a sell. Sign is taken from the SWAPPER's perspective per BalanceDelta.
int128 memecoinDelta = info.memecoinIsToken0 ? delta.amount0() : delta.amount1();
bool isBuy = memecoinDelta > 0;
uint256 absUnspecified = uint256(uint128(isBuy ? memecoinDelta : -memecoinDelta));
uint256 skim = _skimAmount(absUnspecified);
if (skim == 0) return (IHooks.afterSwap.selector, 0);
Currency memecoinCurrency = info.memecoinIsToken0 ? key.currency0 : key.currency1;
POOL_MANAGER.mint(address(this), memecoinCurrency.toId(), skim);
accrued[poolId] += skim;
return (IHooks.afterSwap.selector, int128(int256(skim)));
}
function _skimAmount(uint256 amount) internal pure returns (uint256) {
return (amount * HOOK_FEE_BPS) / BPS_DENOM;
}
// ── self-hosted oracle (§5.2) ────────────────────────────────────────────────────────────────
function _writeObservation(PoolId poolId) internal {
uint16 count = observationCount[poolId];
if (count == 0) return; // not yet registered (afterInitialize writes slot 0)
uint16 idx = observationIndex[poolId];
Observation memory last = _observations[poolId][idx];
if (last.blockTimestamp == block.timestamp) return; // one observation per block, house convention
(, int24 tickBefore,,) = POOL_MANAGER.getSlot0(poolId);
uint32 elapsed = uint32(block.timestamp) - last.blockTimestamp;
int56 tickCumulative = last.tickCumulative + int56(tickBefore) * int56(uint56(elapsed));
uint16 newIdx = uint16((uint256(idx) + 1) % HOOK_OBS_CARDINALITY);
_observations[poolId][newIdx] =
Observation({blockTimestamp: uint32(block.timestamp), tickCumulative: tickCumulative, initialized: true});
observationIndex[poolId] = newIdx;
if (count < HOOK_OBS_CARDINALITY) observationCount[poolId] = count + 1;
}
/// @notice Time-weighted average tick over the trailing `secondsAgo` seconds, read from this
/// hook's own ring buffer (v4 core ships no `observe()`). Reverts `TwapUnavailable` if
/// insufficient history has accumulated yet.
function consultTwap(PoolId poolId, uint32 secondsAgo) public view returns (int24 avgTick) {
uint16 count = observationCount[poolId];
if (count == 0) revert TwapUnavailable();
Observation memory latest = _observations[poolId][observationIndex[poolId]];
int56 cumulativeNow = _cumulativeNow(poolId, latest);
uint256 targetTime = block.timestamp - secondsAgo;
(Observation memory older, Observation memory newer, bool found) =
_findBracket(poolId, targetTime, observationIndex[poolId], count, latest);
if (!found) revert TwapUnavailable(); // not enough history to cover the requested window
int56 cumulativeAtTarget = _interpolate(older, newer, targetTime, cumulativeNow);
int56 delta = cumulativeNow - cumulativeAtTarget;
int56 window = int56(uint56(secondsAgo));
avgTick = int24(delta / window);
if (delta < 0 && (delta % window != 0)) avgTick--; // round toward negative infinity, house convention
}
function _cumulativeNow(PoolId poolId, Observation memory latest) internal view returns (int56) {
(, int24 currentTick,,) = POOL_MANAGER.getSlot0(poolId);
uint32 elapsed = uint32(block.timestamp) - latest.blockTimestamp;
return latest.tickCumulative + int56(currentTick) * int56(uint56(elapsed));
}
/// @dev Walks back from the latest observation — at most `count` (<= 200) iterations — to
/// find the observation pair bracketing `targetTime`.
function _findBracket(PoolId poolId, uint256 targetTime, uint16 latestIdx, uint16 count, Observation memory latest)
internal
view
returns (Observation memory older, Observation memory newer, bool found)
{
uint16 idx = latestIdx;
newer = latest;
for (uint16 i = 0; i < count; i++) {
Observation memory obs = _observations[poolId][idx];
if (obs.blockTimestamp <= targetTime) {
return (obs, newer, true);
}
newer = obs;
idx = idx == 0 ? uint16(HOOK_OBS_CARDINALITY - 1) : idx - 1;
}
return (older, newer, false);
}
/// @dev Linear interpolation between `older` and `newer` (or `cumulativeNow` if `older` is
/// itself the most recent observation) at `targetTime`.
function _interpolate(Observation memory older, Observation memory newer, uint256 targetTime, int56 cumulativeNow)
internal
view
returns (int56)
{
if (older.blockTimestamp == targetTime) return older.tickCumulative;
bool hasNewer = newer.initialized && newer.blockTimestamp > older.blockTimestamp;
uint32 spanEnd = hasNewer ? newer.blockTimestamp : uint32(block.timestamp);
int56 spanCumEnd = hasNewer ? newer.tickCumulative : cumulativeNow;
uint32 span = spanEnd - older.blockTimestamp;
if (span == 0) return older.tickCumulative;
// §12 (int56-overflow, Gate 1 re-verify): compute the interpolation in `int256`. The product
// `slopeNumerator * (targetTime - older.blockTimestamp)` is a tick-cumulative-DELTA (already
// tick×time) times another elapsed span — a tick×time² quantity that overflows `int56`'s
// ~3.6e16 range once a pool has been quiet longer than ~7 days at typical memecoin ticks.
// Since `consultTwap` is exactly what the first-ever staleness conversion (§12/1×3's
// dead-launch fee rescue) and graduation of a long-dormant pool both call, that overflow
// would panic those keeper paths untyped. The RESULT is a linear interpolation strictly
// between two `int56` tick-cumulative endpoints, so it always fits `int56` — only the
// intermediate product needed the wider type.
int256 slopeNumerator = int256(spanCumEnd) - int256(older.tickCumulative);
int256 interpolated = int256(older.tickCumulative)
+ (slopeNumerator * int256(uint256(targetTime - older.blockTimestamp))) / int256(uint256(span));
return int56(interpolated);
}
// ── item 3: batched conversion (memecoin → quote asset) ─────────────────────────────────────
function maxConvertAmount(PoolId poolId) public view returns (uint256) {
return (MAX_CONVERT_BPS_PER_CALL * TOTAL_SUPPLY) / BPS_DENOM;
}
function pendingConvertAmount(PoolId poolId) external view returns (uint256) {
return accrued[poolId];
}
function convertFees(PoolId poolId, uint256 amountHint) external nonReentrant {
_convert(poolId, amountHint);
}
function _convert(PoolId poolId, uint256 amountHint) internal {
PoolInfo storage info = poolInfo[poolId];
if (!info.registered) revert PoolNotRegistered();
// §12-Q: THE ESCROW LOCK APPLIES HERE TOO, EXPLICITLY. `beforeSwap`'s identical check
// (below) cannot see this path: v4-core's `Hooks.beforeSwap` returns early when
// `msg.sender == address(self)` (`lib/v4-core/src/libraries/Hooks.sol:253`), and the
// conversion swap is initiated BY this hook — so a permissionless `convertFees` was the
// one swap able to walk a swept pool's `slot0` for the whole escrow window, against a dust
// LP position added legally during `Curving`, mis-pricing the native reseed and stranding
// the majority of the graduation proceeds (measured: 8,715 bps). Accrual is already dead
// during this window (`beforeSwap` reverts first), so `accrued[poolId]` is a frozen,
// exactly-known number here: this gate DEFERS a fixed amount and puts no new value at
// risk (§3.4), and the lock is always lifted by `_seedGraduatedPool` before any mint on
// every Phase-B path, so nothing can be stranded by deferring.
if (liquidityAddLocked[poolId]) revert SwapLockedDuringGraduation();
uint256 ledger = accrued[poolId];
bool sizeGateMet = ledger >= (MIN_CONVERT_BPS * TOTAL_SUPPLY) / BPS_DENOM;
// Staleness gate: a low-volume pool that has been quiet for `MAX_CONVERT_STALENESS_SECONDS`
// may convert whatever it has accrued, even below the size gate. The anchor for "quiet
// since when" is the last CONVERSION once one has happened, else the last SWAP.
//
// §12 (1×3, Gate 1 sweep): using `lastSwapAt` (not the raw `lastConvertAt == 0`) for the
// FIRST-ever conversion closes a real stranding without reopening the vector the previous
// fix guarded against. Previously `lastConvertAt == 0` was excluded entirely — but then a
// launch whose ONLY trade is the creator's atomic dev-buy (bounded by item 1's dev-alloc
// cap to a hook fee of ~2bps of supply, below `MIN_CONVERT_BPS`'s 5bps) could NEVER clear
// the size gate and, with staleness excluded on the first conversion, had that fee stranded
// in `accrued` forever, not merely deferred. Anchoring on `lastSwapAt` fixes it: the fee
// becomes convertible after `MAX_CONVERT_STALENESS_SECONDS` of real silence. It does NOT
// reopen the immediate-after-launch dust-conversion vector — `lastSwapAt` equals the
// dev-buy's own timestamp at launch (`beforeSwap` set it), so the window is zero right after
// creation and only opens after genuine elapsed quiet; an attacker cannot make `lastSwapAt`
// OLDER, only newer (by trading), so the wait can never be shortcut.
uint256 stalenessAnchor = lastConvertAt[poolId] != 0 ? lastConvertAt[poolId] : lastSwapAt[poolId];
bool stalenessGateMet =
block.timestamp - stalenessAnchor >= MAX_CONVERT_STALENESS_SECONDS && ledger > 0;
if (!sizeGateMet && !stalenessGateMet) revert BelowConvertThreshold();
uint256 cap = maxConvertAmount(poolId);
if (amountHint > cap) revert ConvertAmountTooLarge();
uint256 amountIn = amountHint == 0 ? (ledger < cap ? ledger : cap) : amountHint;
if (amountIn > ledger) amountIn = ledger;
if (amountIn == 0) revert ZeroAmount();
if (block.timestamp - lastConvertAt[poolId] < CONVERT_COOLDOWN_SECONDS && lastConvertAt[poolId] != 0) {
revert CooldownActive(CONVERT_COOLDOWN_SECONDS - (block.timestamp - lastConvertAt[poolId]));
}
lastConvertAt[poolId] = block.timestamp;
int24 twapTick = consultTwap(poolId, CONVERT_TWAP_SECONDS);
uint256 minOut = _fairQuoteOut(info, amountIn, twapTick) * (BPS_DENOM - CONVERT_SWAP_TOL_BPS) / BPS_DENOM;
// §12 (convert partial-fill): the swap may consume less than `amountIn` against a thin pool;
// `consumed` is what actually left the fee ledger, so `accrued` is drawn down by exactly it.
(uint256 quoteOut, uint256 consumed) = _swapMemecoinForQuote(poolId, amountIn, minOut, twapTick);
// §12 (2×6): never burn memecoin fees for a conversion that yields zero quote. For a
// sufficiently LOW-decimal custom quote token (item 2 caps decimals at 24 but has no floor),
// a realistic small-fee swap's real output rounds down to exactly zero whole units. Without
// this guard `accrued` would still be drawn down (the memecoin swapped into the pool for
// nothing) — silently destroying fee value. (§12-N.4: item 6's `isAbandoned()` no longer
// reads ANY value ledger — abandonment is liveness-only — so this guard now stands purely on
// value preservation: a dead low-decimal pool is reclaimable via liveness regardless of
// whether its fee ever leaves `accrued`.) Reverting leaves the fee parked in `accrued`, value
// deferred not destroyed (§3.4), redeemable if a later, larger conversion — or the pool's
// price moving — ever yields a nonzero whole unit.
if (quoteOut == 0) revert ConvertOutputZero();
accrued[poolId] -= consumed;
uint256 protocolShare = (quoteOut * PROTOCOL_SHARE_OF_HOOK_BPS) / BPS_DENOM;
uint256 creatorShare = quoteOut - protocolShare; // remainder, avoids dust loss
pendingTreasuryPayout[poolId] += protocolShare;
_creditQuotePayout(poolId, creatorShare);
emit FeesConverted(poolId, amountIn, quoteOut);
}
function _creditQuotePayout(PoolId poolId, uint256 amount) internal {
if (amount == 0) return;
pendingQuotePayout[poolId] += amount;
}
// ── item 3: claiming — the only functions in this entire pipeline that ever move a real
// ERC20 of the quote asset. Every one is permissionless, balance-delta-measured (mirroring
// `HoodlumLocker`'s confirmed-safe pattern), and independently failing: one recipient's
// frozen/blacklisting behavior never blocks accrual, never blocks conversion, never blocks the
// other recipient's claim. ──────────────────────────────────────────────────────────────────
function claimTreasuryPayout(PoolId poolId) external nonReentrant {
uint256 amount = pendingTreasuryPayout[poolId];
if (amount == 0) revert ZeroAmount();
PoolInfo storage info = poolInfo[poolId];
pendingTreasuryPayout[poolId] = 0;
uint256 received = _payOut(info.quoteToken, TREASURY, amount);
if (received < amount) pendingTreasuryPayout[poolId] += (amount - received); // partial-tax quote token
emit TreasuryPayoutClaimed(poolId, received);
}
/// @notice Pays `feeRecipient[poolId]` their entire `pendingQuotePayout` directly in the quote
/// asset — the creator's base-fee share, always paid in the launch's own quote asset.
function claimFallbackPayout(PoolId poolId) external nonReentrant {
uint256 amount = pendingQuotePayout[poolId];
if (amount == 0) revert ZeroAmount();
PoolInfo storage info = poolInfo[poolId];
pendingQuotePayout[poolId] = 0;
uint256 received = _payOut(info.quoteToken, info.feeRecipient, amount);
if (received < amount) pendingQuotePayout[poolId] += (amount - received);
emit QuotePayoutClaimed(poolId, info.feeRecipient, received);
}
/// @dev Balance-delta measured: a fee-on-transfer quote token under-pays by exactly its own
/// tax (disclosed, not corrupted); a token that reverts entirely on transfer to a
/// specific recipient causes THIS claim to revert, leaving the pending balance intact
/// and re-claimable later — never touching any other pool's or recipient's ledger.
function _payOut(address token, address to, uint256 amount) internal returns (uint256 received) {
uint256 before = IERC20(token).balanceOf(to);
IERC20(token).safeTransfer(to, amount);
received = IERC20(token).balanceOf(to) - before;
}
function _fairQuoteOut(PoolInfo storage info, uint256 memecoinAmount, int24 twapTick) internal view returns (uint256) {
// price = 1.0001^tick, expressed as (memecoin per quote) or (quote per memecoin) depending
// on ordering; computed via the standard tick->sqrtPrice->price relationship.
return HoodlumTickMath.quoteAtTick(memecoinAmount, twapTick, info.memecoinIsToken0);
}
/// @dev The one place per conversion where a real memecoin ERC20 leaves claim-token form: the
/// hook burns its own claim-token balance and swaps the real, settled amount for quote
/// asset through `PoolManager`, guarded by `minOut` (JIT-proof: JIT liquidity only ever
/// helps pass `minOut`) and an in-swap `sqrtPriceLimitX96` catastrophe backstop.
function _swapMemecoinForQuote(PoolId poolId, uint256 amountIn, uint256 minOut, int24 twapTick)
internal
returns (uint256 quoteOut, uint256 consumed)
{
bytes memory result = POOL_MANAGER.unlock(abi.encode(poolId, amountIn, twapTick));
(quoteOut, consumed) = abi.decode(result, (uint256, uint256));
// §12 (convert partial-fill, Gate 1 sweep): on a partial fill the price guard must protect
// the average price of the portion ACTUALLY consumed, not demand the full-`amountIn` output
// (which the swap never produced). `minOut` is linear in amount (`_fairQuoteOut` = amount ×
// TWAP price), so scaling it by `consumed/amountIn` is the exact tolerance floor for the
// consumed portion. `amountIn > 0` is guaranteed by `_convert`'s `ZeroAmount` check.
uint256 scaledMinOut = (minOut * consumed) / amountIn;
if (quoteOut < scaledMinOut) revert ImpactExceeded();
}
// ── unlockCallback dispatch ──────────────────────────────────────────────────────────────
function unlockCallback(bytes calldata data) external onlyPoolManager returns (bytes memory) {
(PoolId poolId, uint256 amountIn, int24 twapTick) = abi.decode(data, (PoolId, uint256, int24));
(uint256 quoteOut, uint256 consumed) = _doConvertSwap(poolId, amountIn, twapTick);
return abi.encode(quoteOut, consumed);
}
/// @dev The one place per conversion where a real memecoin ERC20 leaves claim-token form: burn
/// the hook's own claim-token balance (creating a positive delta that exactly cancels the
/// swap's memecoin-input requirement — no real ERC20 transfer on that leg at all), swap
/// memecoin → quote guarded by `sqrtPriceLimitX96`, then `take()` the real quote-asset
/// output to the hook's own balance so the separate claim functions can pay it out later.
function _doConvertSwap(PoolId poolId, uint256 amountIn, int24 twapTick)
internal
returns (uint256 quoteOut, uint256 consumed)
{
PoolInfo storage info = poolInfo[poolId];
PoolKey memory key = _reconstructKey(info);
bool zeroForOne = info.memecoinIsToken0;
Currency memecoinCurrency = zeroForOne ? key.currency0 : key.currency1;
Currency quoteCurrency = zeroForOne ? key.currency1 : key.currency0;
// §12 (3×5, Gate 1 sweep): this conversion swap is initiated BY the hook, so v4-core's
// `msg.sender == address(self)` exemption skips `beforeSwap` for it. That exemption is
// correct for the fee SKIM (the hook must never re-skim its own conversion), but it ALSO
// skips `beforeSwap`'s oracle-observation write — so a real, price-moving conversion swap
// would go unrecorded, and the self-hosted TWAP (the very oracle every SUBSEQUENT
// conversion's price-impact guard reads) would integrate the pre-conversion tick straight
// across the conversion's own move, silently skewing it. Scope the exemption to the skim
// only: write the observation here explicitly, exactly as `beforeSwap` would have (pre-swap
// tick, one-per-block guarded). Deliberately does NOT touch `lastSwapAt` — a keeper-driven
// conversion is not organic trading and must not mask abandonment liveness (item 6). This
// non-write is now LOAD-BEARING for §12-N.4: `isAbandoned` anchors solely on `lastSwapAt`, so
// if a conversion refreshed it, any permissionless `convertFees` would re-arm abandonment —
// reopening exactly the grief §12-N.4 closes.
//
// ┌── §12-Q CHECKLIST — READ BEFORE ADDING ANY HOOK-INITIATED SWAP ANYWHERE IN THIS FILE ──┐
// │ v4-core skips `beforeSwap` AND `afterSwap` entirely for swaps this hook initiates │
// │ (`Hooks.sol:253` / `:293`, `msg.sender == address(self)`). EVERY thing `beforeSwap` │
// │ does is therefore silently skipped, and each must be a DELIBERATE decision here: │
// │ │
// │ 1. escrow lock check → MUST apply → re-checked in `_convert` (§12-Q). Missing │
// │ it let a permissionless `convertFees` walk │
// │ a swept pool's tick and strand 87% of the │
// │ graduation proceeds. │
// │ 2. oracle observation → MUST apply → written explicitly above (§12 3×5). │
// │ 3. `lastSwapAt` bump → MUST NOT apply→ deliberate: a keeper conversion is not │
// │ organic liveness (§12-N.4, load-bearing). │
// │ 4. the 1% fee skim → MUST NOT apply→ deliberate: never re-skim our own swap. │
// │ │
// │ The lock was missed for a year of review passes because the exemption was understood │
// │ for (2) and (4) and never re-derived for (1). If a fifth thing is ever added to │
// │ `beforeSwap`, add a fifth row here in the same commit. │
// │ │
// │ *** ADDING ANY NEW HOOK-INITIATED SWAP REOPENS §12-Q AND §12-R. *** │
// │ Those two findings are only closed while EVERY swap this contract initiates is gated │
// │ at its own call site — v4-core will not gate it for you, and the escrow window's │
// │ whole safety argument (the reseed price reference is honest) rests on that being │
// │ true of all of them, not just this one. A new hook-initiated swap therefore REQUIRES, │
// │ in the same commit: (a) the escrow-lock check at its call site, (b) an explicit │
// │ decision recorded in this table for each of the four rows above, and (c) a re-sweep │
// │ of the item-3/4/5 pairs. This is the ONLY remaining way the graduation seam's price │
// │ integrity can be defeated — it is a review-process dependency, deliberately written │
// │ into the code because the review process is what failed the first two times. │
// └────────────────────────────────────────────────────────────────────────────────────────┘
_writeObservation(poolId);
POOL_MANAGER.burn(address(this), memecoinCurrency.toId(), amountIn);
BalanceDelta delta = POOL_MANAGER.swap(
key,
SwapParams({
zeroForOne: zeroForOne,
amountSpecified: -int256(amountIn),
sqrtPriceLimitX96: _sqrtPriceLimitFromTick(twapTick, zeroForOne)
}),
""
);
// §12 (convert partial-fill, Gate 1 sweep): an exact-input swap capped by
// `sqrtPriceLimitX96` can consume LESS than `amountIn` — a thin pool (e.g. a freshly
// graduated custom-quote pool seeded with only modest swept reserves) hits the catastrophe
// limit before the full input clears. The `burn` above credited the hook `amountIn` of
// memecoin, but the swap only spent `consumed`; without re-crediting the difference that
// leftover positive delta is left unsettled and `PoolManager` reverts `CurrencyNotSettled`
// (an untyped death for the whole conversion). Re-mint the unconsumed claim tokens —
// settling the delta AND keeping the memecoin-fee backing for `accrued` intact — and report
// `consumed` so `_convert` draws down `accrued` by exactly what was spent, never more.
int128 memecoinDelta = zeroForOne ? delta.amount0() : delta.amount1();
consumed = memecoinDelta < 0 ? uint256(uint128(-memecoinDelta)) : 0;
if (consumed < amountIn) POOL_MANAGER.mint(address(this), memecoinCurrency.toId(), amountIn - consumed);
int128 quoteDelta = zeroForOne ? delta.amount1() : delta.amount0();
quoteOut = quoteDelta > 0 ? uint256(uint128(quoteDelta)) : 0;
if (quoteOut > 0) POOL_MANAGER.take(quoteCurrency, address(this), quoteOut);
}
function _reconstructKey(PoolInfo storage info) internal view returns (PoolKey memory) {
(Currency c0, Currency c1) = info.memecoinIsToken0
? (Currency.wrap(info.memecoinToken), Currency.wrap(info.quoteToken))
: (Currency.wrap(info.quoteToken), Currency.wrap(info.memecoinToken));
return PoolKey({currency0: c0, currency1: c1, fee: info.fee, tickSpacing: info.tickSpacing, hooks: IHooks(address(this))});
}
/// @dev Same-direction catastrophe backstop as V1/`HoodlumRevenueDistributor` (Gate 0 §3.3):
/// a floor `CONVERT_MAX_TICK_TOTAL` below the TWAP for a token0-selling swap, a ceiling
/// above it otherwise — `minOut` (the average-price bound) is the binding guard; this is
/// only the final-price catastrophe bound.
function _sqrtPriceLimitFromTick(int24 twapTick, bool zeroForOne) internal pure returns (uint160) {
int24 offset = zeroForOne ? -CONVERT_MAX_TICK_TOTAL : CONVERT_MAX_TICK_TOTAL;
int24 limitTick = HoodlumTickMath.clampedTick(twapTick, offset);
return uint160(HoodlumTickMath.sqrtPriceX96AtTick(limitTick));
}
/// @notice §12 (2×5): the only add-liquidity restriction this hook ever imposes — reject while
/// `liquidityAddLocked[poolId]` is set (a custom-quote launch's curve pool, swept empty,
/// awaiting its graduated reseed). `msg.sender == self` is NOT exempted from this check
/// by v4-core (`Hooks.beforeModifyLiquidity`'s `noSelfCall` only compares against THIS
/// hook's own address, and FACTORY — the only caller that ever adds liquidity here — is
/// a different contract), so FACTORY's own reseed mint is unlocked immediately before it
/// calls `PoolManager.unlock` in `_seedGraduatedPool`, same as everyone else would need
/// to be.
function beforeAddLiquidity(address, PoolKey calldata key, ModifyLiquidityParams calldata, bytes calldata)
external
view
onlyPoolManager
returns (bytes4)
{
if (liquidityAddLocked[key.toId()]) revert LiquidityAddLocked();
return IHooks.beforeAddLiquidity.selector;
}
// ── unused IHooks callbacks — permission bits for all of these are OFF (getHookPermissions),
// so PoolManager never invokes them; implemented only because Solidity requires every
// interface function to have a body. Each simply returns its own selector, unreachable in
// practice, proven so by the mined address's permission bits (§5.4).
function afterAddLiquidity(
address,
PoolKey calldata,
ModifyLiquidityParams calldata,
BalanceDelta,
BalanceDelta,
bytes calldata
) external pure returns (bytes4, BalanceDelta) {
return (IHooks.afterAddLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA);
}
function beforeRemoveLiquidity(address, PoolKey calldata, ModifyLiquidityParams calldata, bytes calldata)
external
pure
returns (bytes4)
{
return IHooks.beforeRemoveLiquidity.selector;
}
function afterRemoveLiquidity(
address,
PoolKey calldata,
ModifyLiquidityParams calldata,
BalanceDelta,
BalanceDelta,
bytes calldata
) external pure returns (bytes4, BalanceDelta) {
return (IHooks.afterRemoveLiquidity.selector, BalanceDeltaLibrary.ZERO_DELTA);
}
function beforeDonate(address, PoolKey calldata, uint256, uint256, bytes calldata) external pure returns (bytes4) {
return IHooks.beforeDonate.selector;
}
function afterDonate(address, PoolKey calldata, uint256, uint256, bytes calldata) external pure returns (bytes4) {
return IHooks.afterDonate.selector;
}
// ── item 6: mutable fee recipient (the operator's disclosed exception) ─────────────────────
function setFeeRecipient(PoolId poolId, address newRecipient) external {
if (msg.sender != TIMELOCK) revert OnlyTimelock();
PoolInfo storage info = poolInfo[poolId];
if (!info.registered) revert PoolNotRegistered();
emit FeeRecipientChanged(poolId, info.feeRecipient, newRecipient);
info.feeRecipient = newRecipient;
}
// ── §6.7: abandoned-only liveness signal ────────────────────────────────────────────────────
function pokeAlive(PoolId poolId) external {
PoolInfo storage info = poolInfo[poolId];
if (msg.sender != info.creator) revert OnlyCreator();
_touchCreator(poolId);
}
/// @dev Called by `HoodlumPadFactoryV2.claimVest()` as a side effect (Gate 0 §6.7, §12-H fix)
/// — a real, already-expected creator action, not an obscure extra one.
function noteCreatorVestClaim(PoolId poolId, address creator) external {
if (msg.sender != FACTORY) revert UnauthorizedPoolOrigination();
PoolInfo storage info = poolInfo[poolId];
if (info.creator != creator) revert OnlyCreator();
_touchCreator(poolId);
}
/// @dev LOW-MOD-4: stamp the touched poolId and, when a graduation reseed linked it to the
/// launch's OTHER poolId, stamp that twin too — creator liveness is a launch-level fact, and
/// `claimVest` always targets the curve poolId while the live pool may be the graduated one.
/// `creator` is copied verbatim at reseed and never rewritten, so a creator-authenticated
/// touch on one poolId is valid for both by construction. Emits per poolId so an indexer
/// watching either sees it. Single-hop: a graduated pool can never itself be a priorPoolId.
function _touchCreator(PoolId poolId) internal {
lastCreatorTouch[poolId] = block.timestamp;
emit CreatorTouched(poolId, block.timestamp);
PoolId linked = linkedPoolId[poolId];
if (PoolId.unwrap(linked) != bytes32(0)) {
lastCreatorTouch[linked] = block.timestamp;
emit CreatorTouched(linked, block.timestamp);
}
}
/// @dev Called by FACTORY only, at the two edges of the swept-empty window: `true` the moment
/// a custom-quote launch's curve pool is swept to `SweptAwaitingPool` (`graduate()`),
/// `false` immediately before FACTORY's own reseed mint against that same pool
/// (`_seedGraduatedPool`'s same-pair branch) — see `liquidityAddLocked`.
function setLiquidityAddLocked(PoolId poolId, bool locked) external {
if (msg.sender != FACTORY) revert UnauthorizedPoolOrigination();
liquidityAddLocked[poolId] = locked;
}
// ── views used by isAbandoned() (HoodlumFeeRecipientTimelock reads these) ──────────────────
function getPoolInfo(PoolId poolId) external view returns (PoolInfo memory) {
return poolInfo[poolId];
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "poolManager_",
"type": "address",
"internalType": "contract IPoolManager"
},
{
"name": "factory_",
"type": "address",
"internalType": "address"
},
{
"name": "timelock_",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "nonpayable"
},
{
"name": "BelowConvertThreshold",
"type": "error",
"inputs": []
},
{
"name": "ConvertAmountTooLarge",
"type": "error",
"inputs": []
},
{
"name": "ConvertOutputZero",
"type": "error",
"inputs": []
},
{
"name": "CooldownActive",
"type": "error",
"inputs": [
{
"name": "remaining",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "ImpactExceeded",
"type": "error",
"inputs": []
},
{
"name": "LiquidityAddLocked",
"type": "error",
"inputs": []
},
{
"name": "OnlyCreator",
"type": "error",
"inputs": []
},
{
"name": "OnlyPoolManager",
"type": "error",
"inputs": []
},
{
"name": "OnlyTimelock",
"type": "error",
"inputs": []
},
{
"name": "PoolNotRegistered",
"type": "error",
"inputs": []
},
{
"name": "ReentrancyGuardReentrantCall",
"type": "error",
"inputs": []
},
{
"name": "SafeERC20FailedOperation",
"type": "error",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "SwapLockedDuringGraduation",
"type": "error",
"inputs": []
},
{
"name": "TwapUnavailable",
"type": "error",
"inputs": []
},
{
"name": "UnauthorizedPoolOrigination",
"type": "error",
"inputs": []
},
{
"name": "ZeroAmount",
"type": "error",
"inputs": []
},
{
"name": "AccruedMigrated",
"type": "event",
"inputs": [
{
"name": "fromPoolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "toPoolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "CreatorTouched",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "timestamp",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "FeeRecipientChanged",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "oldRecipient",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "newRecipient",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "FeesConverted",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "memecoinIn",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "quoteOut",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "PoolRegistered",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "creator",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "quoteToken",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "memecoinIsToken0",
"type": "bool",
"indexed": false,
"internalType": "bool"
}
],
"anonymous": false
},
{
"name": "QuotePayoutClaimed",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "TreasuryPayoutClaimed",
"type": "event",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"indexed": true,
"internalType": "PoolId"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "CONVERT_COOLDOWN_SECONDS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "CONVERT_MAX_TICK_TOTAL",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "CONVERT_SWAP_TOL_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "CONVERT_TWAP_SECONDS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "CREATOR_SHARE_OF_HOOK_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "FACTORY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "HOOK_FEE_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "HOOK_OBS_CARDINALITY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "MAX_CONVERT_BPS_PER_CALL",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "MAX_CONVERT_STALENESS_SECONDS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "MIN_CONVERT_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "POOL_MANAGER",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "contract IPoolManager"
}
],
"stateMutability": "view"
},
{
"name": "PROTOCOL_SHARE_OF_HOOK_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "TIMELOCK",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "TOTAL_SUPPLY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "TREASURY",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "accrued",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "afterAddLiquidity",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
},
{
"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"
},
{
"name": "",
"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": "",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BalanceDelta"
}
],
"stateMutability": "pure"
},
{
"name": "afterDonate",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
},
{
"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"
},
{
"name": "",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "pure"
},
{
"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": "",
"type": "uint160",
"internalType": "uint160"
},
{
"name": "tick",
"type": "int24",
"internalType": "int24"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "nonpayable"
},
{
"name": "afterRemoveLiquidity",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
},
{
"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"
},
{
"name": "",
"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": "",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "",
"type": "int256",
"internalType": "BalanceDelta"
},
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BalanceDelta"
}
],
"stateMutability": "pure"
},
{
"name": "afterSwap",
"type": "function",
"inputs": [
{
"name": "",
"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": "",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int128",
"internalType": "int128"
}
],
"stateMutability": "nonpayable"
},
{
"name": "beforeAddLiquidity",
"type": "function",
"inputs": [
{
"name": "",
"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": "",
"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": "",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "view"
},
{
"name": "beforeDonate",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
},
{
"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"
},
{
"name": "",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "pure"
},
{
"name": "beforeInitialize",
"type": "function",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"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"
},
{
"name": "",
"type": "uint160",
"internalType": "uint160"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "view"
},
{
"name": "beforeRemoveLiquidity",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
},
{
"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"
},
{
"name": "",
"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": "",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
}
],
"stateMutability": "pure"
},
{
"name": "beforeSwap",
"type": "function",
"inputs": [
{
"name": "",
"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": "",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes4",
"internalType": "bytes4"
},
{
"name": "",
"type": "int256",
"internalType": "BeforeSwapDelta"
},
{
"name": "",
"type": "uint24",
"internalType": "uint24"
}
],
"stateMutability": "nonpayable"
},
{
"name": "claimFallbackPayout",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "claimTreasuryPayout",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "consultTwap",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
},
{
"name": "secondsAgo",
"type": "uint32",
"internalType": "uint32"
}
],
"outputs": [
{
"name": "avgTick",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "convertFees",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
},
{
"name": "amountHint",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"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": "getPoolInfo",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "registered",
"type": "bool",
"internalType": "bool"
},
{
"name": "creator",
"type": "address",
"internalType": "address"
},
{
"name": "feeRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "quoteToken",
"type": "address",
"internalType": "address"
},
{
"name": "memecoinToken",
"type": "address",
"internalType": "address"
},
{
"name": "memecoinIsToken0",
"type": "bool",
"internalType": "bool"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
}
],
"internalType": "struct HoodlumPadHook.PoolInfo"
}
],
"stateMutability": "view"
},
{
"name": "lastConvertAt",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "lastCreatorTouch",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "lastSwapAt",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "linkedPoolId",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"stateMutability": "view"
},
{
"name": "liquidityAddLocked",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "maxConvertAmount",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "noteCreatorVestClaim",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
},
{
"name": "creator",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "observationCount",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "observationIndex",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "pendingConvertAmount",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "pendingQuotePayout",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "pendingTreasuryPayout",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "pokeAlive",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "poolInfo",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "PoolId"
}
],
"outputs": [
{
"name": "registered",
"type": "bool",
"internalType": "bool"
},
{
"name": "creator",
"type": "address",
"internalType": "address"
},
{
"name": "feeRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "quoteToken",
"type": "address",
"internalType": "address"
},
{
"name": "memecoinToken",
"type": "address",
"internalType": "address"
},
{
"name": "memecoinIsToken0",
"type": "bool",
"internalType": "bool"
},
{
"name": "fee",
"type": "uint24",
"internalType": "uint24"
},
{
"name": "tickSpacing",
"type": "int24",
"internalType": "int24"
}
],
"stateMutability": "view"
},
{
"name": "primeHookData",
"type": "function",
"inputs": [
{
"name": "hookData_",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setFeeRecipient",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
},
{
"name": "newRecipient",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setLiquidityAddLocked",
"type": "function",
"inputs": [
{
"name": "poolId",
"type": "bytes32",
"internalType": "PoolId"
},
{
"name": "locked",
"type": "bool",
"internalType": "bool"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "unlockCallback",
"type": "function",
"inputs": [
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "nonpayable"
}
]0x6080806040526004361015610012575f80fd5b5f905f3560e01c90816309f2c0191461272257508063173d13b3146126b35780631abf4fc814611bbd57806321d0ee701461268f578063259982e5146125a25780632d2c5565146125745780632dd31000146125305780632ed9666f1461250257806335d98dbb14611f4f57806335ec137d14611d5e578063384bd6c614611d435780633be05c5114611bc25780633c67eeaa14611bbd5780633ca7cfda146119915780634df62c6b1461196b578063575e24b4146118b85780635fedb7b11461189c5780636217293a1461182c57806362308e85146117e8578063682339421461162a5780636c2bbe7e146115ff5780636c5c6e3d146115d55780636fe7e6eb1461101057806370ab0db914610fe65780637496633d14610fca57806375c7137614610f79578063791d40f014610f5e5780637aadef8b14610f1a578063838ac6fd14610eec578063870b6e5914610ec257806389f69f0114610ea75780638cebd94214610e165780638de652a314610dfb5780639025e53e14610de0578063902d55a514610dba57806391dd7346146107dc5780639ed4daab146107ad5780639f063efc14610781578063a811865a14610757578063a94670df1461072d578063b47b2fb11461067b578063b5fc0ff6146105a8578063b6a8b0fa14610582578063c4e833ce146103f0578063c7a85860146103c6578063dae5f67f1461039c578063dc98354e146102da578063e1b4af69146102b4578063eeb2a5f214610297578063f59452fb1461027b5763f92f23a71461024f575f80fd5b346102785760203660031901126102785760406020916004358152600483522054604051908152f35b80fd5b5034610278578060031936011261027857602060405160fa8152f35b503461027857806003193601126102785760206040516154608152f35b5034610278576102c336612a07565b505050505050602060405163e1b4af6960e01b8152f35b50346102785760e0366003190112610278576102f4612857565b9060a0366023190112610278575061030a612996565b506001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409518116330361038a57807f000000000000000000000000c8d9537c84eaabfa5caf641eba8b3a30cee8fed61691160361037857604051636e4c1aa760e11b8152602090f35b604051630e97f20d60e11b8152600490fd5b60405163f655705d60e01b8152600490fd5b50346102785760203660031901126102785760406020916004358152600583522054604051908152f35b50346102785760203660031901126102785760406020916004358152600483522054604051908152f35b5034610278578060031936011261027857806101c0916101a060405161041581612ac3565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e0820152826101008201528261012082015282610140820152826101608201528261018082015201526040519061047482612ac3565b6001825260016020830152600160408301528060608301528060808301528060a0830152600160c0830152600160e0830152806101008301528061012083015260016101408301526001610160830152806101808301526101a08201526101a0604051916001835260208101511515602084015260408101511515604084015260608101511515606084015260808101511515608084015260a0810151151560a084015260c0810151151560c084015260e0810151151560e084015261010081015115156101008401526101208101511515610120840152610140810151151561014084015261016081015115156101608401526101808101511515610180840152015115156101a0820152f35b50346102785761059136612a07565b5050505050506020604051635b54587d60e11b8152f35b5034610278576040366003190112610278576004356105c5612841565b6001600160a01b037f00000000000000000000000083a928ce374a54050780bf69c3706fdb6dad7d35811633036106695782845260036020526040842060ff8154161561065757600101927f949d8e2c2f1febe8e2a6707ebe4f279a7f71112f3a2c4949c2cbd8fa0b5ab82a604085549381519581861687521694856020820152a26001600160a01b03191617905580f35b60405163739f418560e01b8152600490fd5b604051630e05f48560e11b8152600490fd5b50346102785761016036600319011261027857610696612857565b5060a03660231901126102785760603660c319011261027857610144356001600160401b038111610729576106cf90369060040161289d565b50507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316330361038a57604061070f61012435612e41565b82516001600160e01b03199092168252600f0b6020820152f35b5080fd5b50346102785760203660031901126102785760406020916004358152600783522054604051908152f35b50346102785760203660031901126102785760406020916004358152600a83522054604051908152f35b5034610278576107903661292d565b50505050505050604080516327c18fbf60e21b81525f6020820152f35b50346102785760203660031901126102785760ff60406020926004358152600884522054166040519015158152f35b5034610d8e576020366003190112610d8e576004356001600160401b038111610d8e5761080d90369060040161289d565b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316330361038a578160609181010312610d8e57803590610858604082016129ac565b825f52600360205260405f205f608060405161087381612a95565b828152826020820152826040820152826060820152015260038101549060ff8260a01c165f14610da157600201546001600160a01b03828116939116905b61091d604051946108c186612a95565b6001600160a01b0390811680875293166020860181905260a885901c62ffffff16604087015260c085901c60020b606087015230608087015260a085901c60ff1615610d9a57835b60ff8660a01c165f14610d925750966130b0565b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03163b15610d8e57604051637a94c56560e11b81523060048201526001600160a01b0383166024820152602086013560448201525f8180606481010381837f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03165af18015610d8357610d6e575b509086916109cb6020870135612bd5565b9060ff8560a01c165f14610d60576109f76109f26103e7195b6001600160a01b0393613558565b61359e565b1660405191610a0583612a7a565b60a086901c60ff1615158352602080840191825260408085019384528051633cf3645360e21b815289516001600160a01b0390811660048301528a84015181166024830152918a015162ffffff16604482015260608a015160020b6064820152608090990151811660848a01529351151560a4890152905160c48801529051821660e4870152610120610104870152610124860184905290859061014490829086907f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951165af1938415610d0f578294610d2c575b5060ff8360a01c165f14610d23578360801d5b8281600f0b125f14610d1a57610b096001600160801b0391612e21565b1680955b60208101358210610c45575b5050505060a01c60ff1615610c3d57600f0b5b8381600f0b135f14610c35576001600160801b0316915b82610b79575b610b758383604051916020830152604082015260408152610b6981612a7a565b604051918291826129db565b0390f35b7f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03163b15610c3157604051630b0d9c0960e01b81526001600160a01b039182166004820152306024820152604481018490529084908290606490829084907f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951165af18015610c265715610b4957610c188491612ab0565b610c225782610b49565b8280fd5b6040513d86823e3d90fd5b8380fd5b508291610b43565b60801d610b2c565b906020610c53920135612b79565b907f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03163b15610c2257604051630ab714fb60e11b81523060048201526001600160a01b0390911660248201526044810191909152818180606481010381837f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03165af18015610d0f57610cf7575b8481610b19565b610d0090612ab0565b610d0b57845f610cf0565b8480fd5b6040513d84823e3d90fd5b50818095610b0d565b83600f0b610aec565b9093506020813d602011610d58575b81610d4860209383612adf565b810103126107295751925f610ad9565b3d9150610d3b565b6109f76109f26103e86109e4565b610d7a91929750612ab0565b5f95905f6109ba565b6040513d5f823e3d90fd5b5f80fd5b9050966130b0565b8093610909565b600201546001600160a01b0390811692908216906108b1565b34610d8e575f366003190112610d8e5760206040516b033b2e3c9fd0803ce80000008152f35b34610d8e575f366003190112610d8e57602060405160c88152f35b34610d8e575f366003190112610d8e57602060405160328152f35b34610d8e576020366003190112610d8e576004355f52600360205261010060405f2080549060018060a01b03806001830154169160038260028301541691015492826040519560ff81161515875260081c166020860152604085015260608401528116608083015260ff8160a01c16151560a083015262ffffff8160a81c1660c083015260c01c60020b60e0820152f35b34610d8e575f366003190112610d8e57602060405160648152f35b34610d8e576020366003190112610d8e576004355f526009602052602060405f2054604051908152f35b34610d8e576020366003190112610d8e576004355f526001602052602061ffff60405f205416604051908152f35b34610d8e575f366003190112610d8e576040517f00000000000000000000000083a928ce374a54050780bf69c3706fdb6dad7d356001600160a01b03168152602090f35b34610d8e575f366003190112610d8e57602060405160058152f35b34610d8e576020366003190112610d8e576004355f8181526003602052604090205460081c6001600160a01b03163303610fb857610fb690612fc3565b005b6040516308f78f9960e31b8152600490fd5b34610d8e575f366003190112610d8e5760206040516107088152f35b34610d8e576020366003190112610d8e576004355f52600b602052602060405f2054604051908152f35b34610d8e57610100366003190112610d8e5761102a612857565b60a0366023190112610d8e5761103e612996565b5060e4358060020b03610d8e577f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316330361038a576001600160a01b037f000000000000000000000000c8d9537c84eaabfa5caf641eba8b3a30cee8fed68116911603610378576040516110b981612a95565b602435906001600160a01b0382168203610d8e578181526044356001600160a01b0381168103610d8e578060208301526064359262ffffff84168403610d8e57836040840152608435928360020b8403610d8e576060810184905260a435906001600160a01b0382168203610d8e5760a09160808201522092604051945f86600c549161114583612b93565b8083526001841680156115b35760011461156b575b50611170929161116b910389612adf565b612b93565b806114ec575b5060a086805181010312610d8e5761119060208701612e00565b9061119d60408801612e00565b966111aa60608201612e14565b9060a06111b960808301612e14565b910151936001600160a01b031690156114bd5750825f52600360205260405f209384549560ff871615610657577fb21bbda615e98eaea9c214226d043a6d614e9f42b05a2f24fe88b79e61e8ebab978960409860018060a01b039060081c16976001808060a01b039101541696805f526009602052895f2054825f528a5f2055600b602052808a5f2055805f52818a5f20556004602052895f208054908161147f575b505050505b831561146e57506001600160a01b0316925b6003875161128081612a5e565b6001815260018060a01b03881660208201528881019660018060a01b031687526060810160018060a01b038d168152608082019660018060a01b0316875260a082019515159788875262ffffff60c084019516855260e083019560020b86528c5f528360205260208b5f209361130581511515869060ff801983541691151516179055565b01518354610100600160a81b03191660089190911b610100600160a81b0316178355516001830180546001600160a01b03199081166001600160a01b03938416179091559151600284018054909316908216179091559551910180549451925193516001600160d81b0319909516919095161790151560a01b60ff60a01b161760a89190911b62ffffff60a81b161762ffffff60c01b60c09290921b91909116179055825163ffffffff6113b882612a7a565b804216825260208201905f82526affffffffffffff000000008684019160018352895f525f602052875f209451168454935160201b9260ff60581b9051151560581b16936bffffffffffffffffffffffff1916179116171790556001602052825f2061ffff199081815416905560026020526001845f2091825416179055600a60205242835f205582519560018060a01b03168652602086015260018060a01b031693a3604051636fe7e6eb60e01b8152602090f35b6001600160a01b0316939050611273565b7fda7d8b168fc652237d0ec9ba2a21d0beeeb6009af1934d68cccbaedca66bfed9915f60209255845f52808d5f20558c51908152a3898c808061125c565b937fb21bbda615e98eaea9c214226d043a6d614e9f42b05a2f24fe88b79e61e8ebab9693506040958594611261565b601f811160011461150357505f600c555b86611176565b7fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c85b601f820160051c5f80516020613b2c833981519152018110611560575050600c5f525f600c555f5f80516020613b2c833981519152556114fd565b5f8155600101611525565b600c5f90815291505f80516020613b2c8339815191525b818310611598575050810160200161117061115a565b80602092948385600194549201015201910190918992611582565b5060ff19841660208085019190915290151560051b830101905061117061115a565b34610d8e576020366003190112610d8e576004355f526006602052602060405f2054604051908152f35b34610d8e5761160d3661292d565b5050505050505060408051633615df3f60e11b81525f6020820152f35b34610d8e576040366003190112610d8e5760043560243563ffffffff90818116809103610d8e57825f526020926002845261ffff8060405f20541680156117d65761171890835f525f875261169661169060405f2060018a528560405f20541690612da9565b50612dcc565b906116f86116c4867f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951613466565b50509890506116f06116db8286511683421661305d565b998b8601519260069b168b0b9060020b613073565b90890b61308a565b946117038742612b79565b8095825f5260018b5260405f20541691613292565b929092156117d65761172b928492613334565b830b90830b0391667fffffffffffff1991828412667fffffffffffff85131761179f57810b92810b9083156117c2575f199282148484141661179f5783820560020b935f831292836117b3575b50505061178c575b506040519060020b8152f35b90627fffff19811461179f570182611780565b634e487b7160e01b5f52601160045260245ffd5b07900b15159050848080611778565b634e487b7160e01b5f52601260045260245ffd5b604051630a37c5f160e11b8152600490fd5b34610d8e575f366003190112610d8e576040517f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b03168152602090f35b34610d8e576040366003190112610d8e576024358015158103610d8e577f000000000000000000000000c8d9537c84eaabfa5caf641eba8b3a30cee8fed66001600160a01b0316330361037857610fb6906004355f52600860205260405f209060ff801983541691151516179055565b34610d8e575f366003190112610d8e5760206040516103e88152f35b34610d8e57610140366003190112610d8e576118d2612857565b5060a0366023190112610d8e5760603660c3190112610d8e57610124356001600160401b038111610d8e5761190b90369060040161289d565b50507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409516001600160a01b0316330361038a57606062ffffff61194b612be5565b906040939293519363ffffffff60e01b1684526020840152166040820152f35b34610d8e576020366003190112610d8e5760206040516a0422ca8b0a00a4250000008152f35b34610d8e57602080600319360112610d8e57600435906119af61302e565b815f526006815260405f2054908115611bab57825f526003815260405f20600682525f6040812055600260018060a01b039101541691604051926370a0823160e01b80855273561deb125684f3a6f39414897cc9309658321f4a908160048701528486602481865afa958615610d83575f96611b7c575b5060405163a9059cbb60e01b5f528260045284602452855f60448180885af160015f5114811615611b5d575b8160405215611b47575090602485926040519485938492835260048301525afa908115610d83575f91611afa575b507f5e4ef75c403b3d0c58e49b2cc9ffa4634c27afd53f050ccff701e62245594fac93611aac91612b79565b9081818110611ad2575b5050604051908152a260015f80516020613b4c83398151915255005b611adb91612b79565b845f5260068352611af160405f20918254612b86565b90558481611ab6565b90508281813d8311611b40575b611b118183612adf565b81010312610d8e57517f5e4ef75c403b3d0c58e49b2cc9ffa4634c27afd53f050ccff701e62245594fac611a80565b503d611b07565b635274afe760e01b815260048101849052602490fd5b6001811516611b7357843b15153d151616611a52565b503d5f823e3d90fd5b9095508481813d8311611ba4575b611b948183612adf565b81010312610d8e57519487611a26565b503d611b8a565b604051631f2a200560e01b8152600490fd5b612881565b34610d8e57602080600319360112610d8e576001600160401b03600435818111610d8e57611bf490369060040161289d565b917f000000000000000000000000c8d9537c84eaabfa5caf641eba8b3a30cee8fed66001600160a01b03163303610378578211611d2f57611c36600c54612b93565b601f8111611ce3575b505f92601f8311600114611c7b57509181925f92611c70575b50505f19600383901b1c191660019190911b17600c55005b013590508280611c58565b601f198316935f80516020613b2c83398151915292915f905b868210611ccb5750508360019510611cb2575b505050811b01600c55005b01355f19600384901b60f8161c19169055828080611ca7565b80600184968294958701358155019501920190611c94565b5f80516020613b2c833981519152601f840160051c81019160208510611d25575b601f0160051c01905b818110611d1a5750611c3f565b5f8155600101611d0d565b9091508190611d04565b634e487b7160e01b5f52604160045260245ffd5b34610d8e575f366003190112610d8e57602060405160b48152f35b34610d8e57602080600319360112610d8e57600435611d7b61302e565b805f526007825260405f2054918215611bab57815f526003815260405f2090600781525f604081205560018060a01b0360018160028501541693018181541693604051946370a0823160e01b8087528160048801528587602481865afa968715610d83575f97611f20575b5060405163a9059cbb60e01b5f528260045289602452865f60448180885af160015f5114811615611f0a575b8160405215611b47575090602486926040519485938492835260048301525afa908115610d83575f91611ebd575b507f866614f2a10441c97fee389a1a6b0a09a735158019f78535954f8f33096fdeef94611e6c91612b79565b9586818110611e95575b5050541693604051908152a360015f80516020613b4c83398151915255005b611e9e91612b79565b855f5260078452611eb460405f20918254612b86565b90558686611e76565b90508381813d8311611f03575b611ed48183612adf565b81010312610d8e57517f866614f2a10441c97fee389a1a6b0a09a735158019f78535954f8f33096fdeef611e40565b503d611eca565b6001811516611b7357843b15153d151616611e12565b9096508581813d8311611f48575b611f388183612adf565b81010312610d8e57519589611de6565b503d611f2e565b34610d8e576040366003190112610d8e576004356024803590611f7061302e565b825f5260206003815260405f209160ff8354161561065757845f526008825260ff60405f2054166124f057845f526004825260405f2054936969e10de76676d080000085109060059182855260405f205415155f146124dc57875f52828552615460611fe160405f20545b42612b79565b1015806124d3575b816124ca575b506124b8576a0422ca8b0a00a425000000908181116124a6578061249e5750808610156124995750845b945b808611612491575b508415611bab57855f528083526107088061204260405f205442612b79565b108061247e575b61244c5750855f5282524260405f20556002825261ffff8060405f2054169182156117d657865f525f845261208f61169060405f20600187528460405f20541690612da9565b927f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951926120bc8985613466565b50509590506120f863ffffffff6120f06120db8285511683421661305d565b988a8501519260069a168a0b9060020b613073565b90880b61308a565b9260b319420192428411612439579061212092918c5f5260018a5260405f205416848d613292565b929092156117d657612133928492613334565b840b90840b03667fffffffffffff198112667fffffffffffff8213176123e657830b945f60b4870560020b965f81129081612427575b506123fa575b5060ff600361218592015460a01c168688613514565b91612616928381029381850414901517156123e6576127108093049060405196898789015288604089015260020b60608801526060875260808701906001600160401b0390888310828411176123d35760408390526348c8949160e01b83525f9083908183607f198d6121fb81608481016129db565b0301926001600160a01b03165af1978815610d83575f9861233c575b505050604086805181010312610d8e576040858701519601519081810290808204831490151715612329578761224c91612bcb565b861061231757851561230557875f526004855261226e60405f20918254612b79565b905561138885029061138719868304016122f25750604094927ffc2826d2fffc53ee4b5a04c6a5e9689a7f49c60542c1118669e4164d93d905829694926122d692046122ba8186612b79565b91895f5284526122ce875f20918254612b86565b905587613442565b8351928352820152a260015f80516020613b4c83398151915255005b634e487b7160e01b5f9081526011600452fd5b604051632197f53760e21b8152600490fd5b604051632d14928560e01b8152600490fd5b82634e487b7160e01b5f5260116004525ffd5b90919297503d805f853e6123508185612adf565b810192878260808601950312610d8e575190828211610d8e57019082609f83011215610d8e5760808201519081116123c05760405192612399601f8301601f1916890185612adf565b81845260a08284010111610d8e576123b79160a088850191016129ba565b94888080612217565b83634e487b7160e01b5f5260416004525ffd5b84634e487b7160e01b5f5260416004525ffd5b50634e487b7160e01b5f9081526011600452fd5b909590627fffff19821461241457505f19019460ff61216f565b634e487b7160e01b815260116004529050fd5b91505060b45f9107850b15158a612169565b85634e487b7160e01b5f5260116004525ffd5b9192865f525261246060405f205442612b79565b81039081116123e6576040519063c1ab61a160e01b82526004820152fd5b50865f5281845260405f20541515612049565b945086612023565b612019565b90509461201b565b60405163d837d81b60e01b8152600490fd5b604051634db2c40160e01b8152600490fd5b90501588611fef565b50861515611fe9565b600a8552615460611fe160405f2054611fdb565b6040516364b9487160e01b8152600490fd5b34610d8e576020366003190112610d8e576004355f526002602052602061ffff60405f205416604051908152f35b34610d8e575f366003190112610d8e576040517f000000000000000000000000c8d9537c84eaabfa5caf641eba8b3a30cee8fed66001600160a01b03168152602090f35b34610d8e575f366003190112610d8e57602060405173561deb125684f3a6f39414897cc9309658321f4a8152f35b34610d8e576125b0366128ca565b506001600160a01b03935050507f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e409518216330361038a5760a081360312610d8e57604051906125fd82612a95565b6126068161286d565b82526126146020820161286d565b602083015260408101359062ffffff82168203610d8e57608091604084015261263f606082016129ac565b606084015201359182168203610d8e5760a0916080820152205f52600860205260ff60405f20541661267d5760405163259982e560e01b8152602090f35b604051630af8089f60e41b8152600490fd5b34610d8e5761269d366128ca565b5050505050602060405163021d0ee760e41b8152f35b34610d8e576040366003190112610d8e576004356126cf612841565b6001600160a01b037f000000000000000000000000c8d9537c84eaabfa5caf641eba8b3a30cee8fed68116330361037857825f5260036020528060405f205460081c16911603610fb857610fb690612fc3565b34610d8e576020366003190112610d8e5760e0816127405f93612a5e565b8281528260208201528260408201528260608201528260808201528260a08201528260c082015201526004355f52600360205261010060405f2060405161278681612a5e565b81549060ff821615159283825260018060a01b039283602084019160081c1681528380600184015416604085019081526003826002860154169460608701958652015495869481608088019381881685528160a08a019760ff8a60a01c161515895260e062ffffff9b8c60c082019c60a81c168c52019b60c01c60020b8c526040519c8d52511660208c0152511660408a0152511660608801525116608086015251151560a0850152511660c08301525160020b60e0820152f35b602435906001600160a01b0382168203610d8e57565b600435906001600160a01b0382168203610d8e57565b35906001600160a01b0382168203610d8e57565b34610d8e575f366003190112610d8e5760206040516113888152f35b9181601f84011215610d8e578235916001600160401b038311610d8e5760208381860195010111610d8e57565b90610160600319830112610d8e576004356001600160a01b0381168103610d8e579160a0602319820112610d8e57602491608060c319830112610d8e5760c49161014435906001600160401b038211610d8e576129299160040161289d565b9091565b906101a0600319830112610d8e576004356001600160a01b0381168103610d8e579160a0602319820112610d8e57602491608060c319830112610d8e5760c4916101443591610164359161018435906001600160401b038211610d8e576129299160040161289d565b60c435906001600160a01b0382168203610d8e57565b35908160020b8203610d8e57565b5f5b8381106129cb5750505f910152565b81810151838201526020016129bc565b604091602082526129fb81518092816020860152602086860191016129ba565b601f01601f1916010190565b610120600319820112610d8e576004356001600160a01b0381168103610d8e579160a0602319830112610d8e5760249160c4359160e4359161010435906001600160401b038211610d8e576129299160040161289d565b61010081019081106001600160401b03821117611d2f57604052565b606081019081106001600160401b03821117611d2f57604052565b60a081019081106001600160401b03821117611d2f57604052565b6001600160401b038111611d2f57604052565b6101c081019081106001600160401b03821117611d2f57604052565b90601f801991011681019081106001600160401b03821117611d2f57604052565b60a0906023190112610d8e5760405190612b1982612a95565b6001600160a01b03826024358281168103610d8e5781526044358281168103610d8e57602082015260643562ffffff81168103610d8e5760408201526084358060020b8103610d8e57606082015260a4359182168203610d8e5760800152565b9190820391821161179f57565b9190820180921161179f57565b90600182811c92168015612bc1575b6020831014612bad57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691612ba2565b81156117c2570490565b600160ff1b811461179f575f0390565b5f60a0612bf136612b00565b2091825f526008602052604060ff815f205416612d9957612c11846130b0565b835f52600a60205242815f20556003602052805f209360ff85541615612d855760e4355f811260c43596871515809803610d8e576003015460a01c60ff169687151590821403612d6f57612c73919015612c6e57612c6e90612bd5565b613259565b948515612d5a5715612d43576024356001600160a01b0381168103610d8e575b6001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951811691823b15610d8e578451630ab714fb60e11b81523060048201529116602482015260448101879052905f908290606490829084905af18015612d3957612d26575b50835260046020528220612d14848254612b86565b90556315d7892d60e21b9260801b9190565b612d31919450612ab0565b5f925f612cff565b83513d5f823e3d90fd5b6044356001600160a01b0381168114612c93575f80fd5b506315d7892d60e21b94505f93508392915050565b506315d7892d60e21b95505f9450849392505050565b506315d7892d60e21b93505f925082919050565b516364b9487160e01b8152600490fd5b60c8821015612db85701905f90565b634e487b7160e01b5f52603260045260245ffd5b90604051612dd981612a7a565b604060ff82945463ffffffff811684528060201c60060b602085015260581c161515910152565b51906001600160a01b0382168203610d8e57565b51908115158203610d8e57565b600f0b6f7fffffffffffffffffffffffffffffff19811461179f575f0390565b905f60a0612e4e36612b00565b2090815f52600360205260405f209360ff85541615612f9b5760c43594851515809603610d8e576003015460a01c60ff16945f60e435121485151514612f9b576001600160801b03612eb891865f14612fbb5760801d5b5f81600f0b135f14612fad575b16613259565b938415612f9b5715612f82576024356001600160a01b0381168103610d8e57915b6001600160a01b037f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951811693843b15610d8e57604051630ab714fb60e11b81523060048201529116602482015260448101869052925f908490606490829084905af1928315610d8357604093612f6f575b508152600460205220612f5e838254612b86565b905563b47b2fb160e01b91600f0b90565b612f7a919250612ab0565b5f905f612f4a565b6044356001600160a01b0381168103610d8e5791612ed9565b5063b47b2fb160e01b93505f92915050565b612fb690612e21565b612eb2565b600f0b612ea5565b602090805f52600982524260405f2055806040514281527f9063e6aab3b2f8cc04013a307890be6d1fa2af650a4e6040937694c8484ed51b938491a25f52600b60205260405f20549081613015575050565b815f5260096020524260405f20556020604051428152a2565b5f80516020613b4c833981519152600281541461304b5760029055565b604051633ee5aeb560e01b8152600490fd5b63ffffffff918216908216039190821161179f57565b9060060b9060060b02908160060b91820361179f57565b9060060b9060060b0190667fffffffffffff198212667fffffffffffff83131761179f57565b805f526020906002825261ffff604081815f205416928315613252576001855282825f205416935f86526130e961169086855f20612da9565b63ffffffff958682511642146132485761315b613126857f0000000000000000000000008366a39cc670b4001a1121b8f6a443a643e40951613466565b5050939050613152894216948a8c613141828651168961305d565b940151931660060b9060020b613073565b9060060b61308a565b906001810180911161179f5760c8879106169685519261317a84612a7a565b83528883019160060b82528583019060018252855f525f8a5261319f89885f20612da9565b94909461323557518454935192516bffffffffffffffffffffffff199094169116176affffffffffffff00000000918a1b919091161790151560581b60ff60581b161790555f82815260018752839020805461ffff19908116909617905560c8811061320e575b505050505050565b6001019483861161179f576002915f52525f209216908254161790555f8080808080613206565b634e487b7160e01b5f525f60045260245ffd5b5050505050505050565b5050505050565b60648102908082046064149015171561179f57612710900490565b6040519061328182612a7a565b5f6040838281528260208201520152565b91939461329d613274565b946132a6613274565b5095925f935b61ffff90818716828716101561332657825f525f6020526132d36116908a60405f20612da9565b908563ffffffff835116111561331557509781168061330057505061ffff600160c75b95011693966132ac565b5f190190811161179f57600161ffff916132f6565b985095505050935050509190600190565b9697505f9550919350505050565b9291909163ffffffff90818551169083821461343357604085015115159485613426575b91613380918493875f1461341d5784815116975b156134165760209150015160060b9561305d565b169283156134085760060b60208501805160060b93848303935f86128486128116908587139015161761179f576133be925160060b97511690612b79565b9283830293600160ff1b938482145f82121661179f578505149114171561179f5781145f1983141661179f5705905f828201928312911290801582169115161761179f5760060b90565b505050506020015160060b90565b509561305d565b8442169761336c565b8051841683109550613358565b50505050506020015160060b90565b8115613462575f52600760205261345e60405f20918254612b86565b9055565b5050565b602060249392604051828101918252600660408201526040815261348981612a7a565b519020604051631e2eaeaf60e01b81526004810191909152936001600160a01b0392859190829085165afa928315610d83575f936134e0575b508216918060a01c60020b9162ffffff808360b81c169260d01c1690565b9092506020813d60201161350c575b816134fc60209383612adf565b81010312610d8e5751915f6134c2565b3d91506134ef565b919061351f9061359e565b901561353a576135328161353793613a37565b613a37565b90565b8061354491613a37565b8061354f5750505f90565b61353791613a8d565b9060020b9060020b01627fffff198112627fffff82131761179f578060020b620d89e7198082126135985750620d89e8809113613593575090565b905090565b91505090565b60020b5f811215613a31576135b281612bd5565b6001811615613a1f576001600160881b036ffffcb933bd6fad37aa2d162d1a5940015b1691600282166139f3575b6004918281166139c7575b6008811661399b575b6010811661396f575b60208116613943575b60408116613917575b6080908181166138ec575b61010081166138c1575b6102008116613896575b610400811661386b575b6108008116613840575b6110008116613815575b61200081166137ea575b61400081166137bf575b6180008116613794575b620100008116613769575b62020000811661373f575b620400008116613703575b62080000166136c7575b505f126136a4575b5060201c90565b81156136b457505f19045f61369d565b601290634e487b7160e01b5f525260245ffd5b6b048a170391f7dc42444e8fa2939193918281029281840414901517156136f0571c915f613695565b601183634e487b7160e01b5f525260245ffd5b936d2216e584f5fa1ea926041bedfe989081810291818304149015171561372c57811c9361368b565b601184634e487b7160e01b5f525260245ffd5b936e5d6af8dedb81196699c329225ee6049081810291818304149015171561372c57811c93613680565b936f09aa508b5b7a84e1c677de54f3e99bc99081810291818304149015171561372c57811c93613675565b936f31be135f97d08fd981231505542fcfa69081810291818304149015171561372c57811c9361366a565b936f70d869a156d2a1b890bb3df62baf32f79081810291818304149015171561372c57811c93613660565b936fa9f746462d870fdf8a65dc1f90e061e59081810291818304149015171561372c57811c93613656565b936fd097f3bdfd2022b8845ad8f792aa58259081810291818304149015171561372c57811c9361364c565b936fe7159475a2c29b7443b29c7fa6e889d99081810291818304149015171561372c57811c93613642565b936ff3392b0822b70005940c7a398e4b70f39081810291818304149015171561372c57811c93613638565b936ff987a7253ac413176f2b074cf7815e549081810291818304149015171561372c57811c9361362e565b936ffcbe86c7900a88aedcffc83b479aa3a49081810291818304149015171561372c57811c93613624565b936ffe5dee046a99a2a811c461f1969c30539081810291818304149015171561372c57811c9361361a565b926fff2ea16466c96a3843ec78b326b52861908181029181830414901517156136f05760801c9261360f565b926fff973b41fa98c081472e6896dfb254c0908181029181830414901517156136f05760801c92613606565b926fffcb9843d60f6159c9db58835c926644908181029181830414901517156136f05760801c926135fd565b926fffe5caca7e10e4e61c3624eaa0941cd0908181029181830414901517156136f05760801c926135f4565b926ffff2e50f5f656932ef12357cf3c7fdcc908181029181830414901517156136f05760801c926135eb565b916ffff97272373d413259a46990580e213a9081810291818304149015171561179f5760801c916135e0565b6001600160881b03600160801b6135d5565b806135b2565b5f198282099082810292838084109303928084039314613a8457600160601b9183831115613a72570990828211900360a01b910360601c1790565b634e487b715f5260116020526024601cfd5b50505060601c90565b600160601b915f19838309928260601b92838086109503948086039514613b1e5784831115613b065790829109815f038216809204600280826003021880830282030280830282030280830282030280830282030280830282030280920290030293600183805f03040190848311900302920304170290565b82634e487b715f52156003026011186020526024601cfd5b5050906135379250612bcb56fedf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c79b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a2646970667358221220d66fdab79cd61ebd3b81c8a0d552cd275d4470a80757130086a1bb34f871ea3064736f6c63430008180033
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
WETH (WETH) | WETH | 0.006884 | $1,907.04 | $13.13 |
| 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 |
|---|---|---|---|
| 0x78d830…67bf88 | 5 days agoWed, 12 Aug 2026 01:15:09 UTC | 0x5e4ef7…4fac | [0] 0xb263665480f9…0bf23362 data: 0x000000000000000000…de55f0a2 |
| 0x3812fb…b83b1b | 5 days agoWed, 12 Aug 2026 01:15:06 UTC | 0xfc2826…0582 | [0] 0xb263665480f9…0bf23362 data: 0x000000000000000000…bcabe144 |
| 0x96e3b0…3ad39d | 5 days agoTue, 11 Aug 2026 19:09:29 UTC | 0xb21bbd…ebab | [0] 0xb263665480f9…0bf23362 [1] 0x000000000000…aa90d0e6 data: 0x000000000000000000…00000000 |
| 0x9e1833…6d21c4 | 18 days agoThu, 30 Jul 2026 16:05:05 UTC | 0x5e4ef7…4fac | [0] 0x08d0d7b61970…531f29bc data: 0x000000000000000000…7b877873 |
| 0x1c97b9…0b2c81 | 18 days agoThu, 30 Jul 2026 16:05:03 UTC | 0xfc2826…0582 | [0] 0x08d0d7b61970…531f29bc data: 0x000000000000000000…f70ef0e7 |
| 0x9b41ab…5077bd | 18 days agoThu, 30 Jul 2026 15:55:07 UTC | 0x5e4ef7…4fac | [0] 0x31948489672a…bb3c908d data: 0x000000000000000000…3b4e5bb5 |
| 0x14d9dd…27b16f | 18 days agoThu, 30 Jul 2026 15:55:05 UTC | 0xfc2826…0582 | [0] 0x31948489672a…bb3c908d data: 0x000000000000000000…769cb76a |
| 0x495b68…6fa16c | 18 days agoThu, 30 Jul 2026 06:56:08 UTC | 0x5e4ef7…4fac | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…ae108ce1 |
| 0x692040…744f90 | 18 days agoThu, 30 Jul 2026 06:56:06 UTC | 0xfc2826…0582 | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…5c2119c3 |
| 0xe18434…fb2665 | 18 days agoWed, 29 Jul 2026 19:38:08 UTC | 0x5e4ef7…4fac | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…817c186d |
| 0x60797d…e9449d | 18 days agoWed, 29 Jul 2026 19:38:06 UTC | 0xfc2826…0582 | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…02f830db |
| 0xab8f9b…7be4c6 | 18 days agoWed, 29 Jul 2026 19:07:33 UTC | 0x866614…deef | [0] 0xbd34f151c53f…3dbd6b8a [1] 0x000000000000…4c8e1ce0 data: 0x000000000000000000…a72e3a0a |
| 0xf6992b…23aa95 | 19 days agoWed, 29 Jul 2026 13:37:08 UTC | 0x5e4ef7…4fac | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…3a7a3e51 |
| 0x8544e7…315a70 | 19 days agoWed, 29 Jul 2026 13:37:06 UTC | 0xfc2826…0582 | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…74f47ca3 |
| 0x1dc8b9…9431f5 | 19 days agoWed, 29 Jul 2026 13:33:16 UTC | 0x9063e6…d51b | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…6a6a011c |
| 0x4a4b85…909668 | 19 days agoWed, 29 Jul 2026 04:38:09 UTC | 0x5e4ef7…4fac | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…2bdd6078 |
| 0x7e3874…93a5de | 19 days agoWed, 29 Jul 2026 04:38:07 UTC | 0xfc2826…0582 | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…57bac0f1 |
| 0x3fb030…ed0bcb | 19 days agoWed, 29 Jul 2026 02:49:10 UTC | 0x5e4ef7…4fac | [0] 0xbd34f151c53f…3dbd6b8a data: 0x000000000000000000…8d3bb0db |
| 0x7199ca…12c7da | 19 days agoWed, 29 Jul 2026 02:49:07 UTC | 0xfc2826…0582 | [0] 0xbd34f151c53f…3dbd6b8a data: 0x000000000000000000…1a7761b7 |
| 0x4078af…d37742 | 19 days agoWed, 29 Jul 2026 02:10:11 UTC | 0x5e4ef7…4fac | [0] 0xbd34f151c53f…3dbd6b8a data: 0x000000000000000000…fee6cd27 |
| 0xfa4548…28548c | 19 days agoWed, 29 Jul 2026 02:10:09 UTC | 0xfc2826…0582 | [0] 0xbd34f151c53f…3dbd6b8a data: 0x000000000000000000…fdcd9a4f |
| 0xd1ecde…7d9442 | 19 days agoTue, 28 Jul 2026 22:37:09 UTC | 0x5e4ef7…4fac | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…3584b8d4 |
| 0x1896a5…14ce73 | 19 days agoTue, 28 Jul 2026 22:37:07 UTC | 0xfc2826…0582 | [0] 0xad9e32a4561a…4df8a94b data: 0x000000000000000000…6b0971a9 |
| 0xe08ff3…792bf5 | 19 days agoTue, 28 Jul 2026 20:50:11 UTC | 0x5e4ef7…4fac | [0] 0xbd34f151c53f…3dbd6b8a data: 0x000000000000000000…142327c5 |
| 0xe0d3c4…4c3c50 | 19 days agoTue, 28 Jul 2026 20:50:08 UTC | 0xfc2826…0582 | [0] 0xbd34f151c53f…3dbd6b8a data: 0x000000000000000000…28464f8b |
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x78d830…67bf88 | claimTreasuryPayout | 34,122,981 | 5 days agoWed, 12 Aug 2026 01:15:09 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000460 | |
| 0x3812fb…b83b1b | convertFees | 34,122,958 | 5 days agoWed, 12 Aug 2026 01:15:06 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00001908 | |
| 0x9e1833…6d21c4 | claimTreasuryPayout | 23,445,036 | 18 days agoThu, 30 Jul 2026 16:05:05 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000111 | |
| 0x1c97b9…0b2c81 | convertFees | 23,445,012 | 18 days agoThu, 30 Jul 2026 16:05:03 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000366 | |
| 0x9b41ab…5077bd | claimTreasuryPayout | 23,439,064 | 18 days agoThu, 30 Jul 2026 15:55:07 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000166 | |
| 0x14d9dd…27b16f | convertFees | 23,439,040 | 18 days agoThu, 30 Jul 2026 15:55:05 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000389 | |
| 0x495b68…6fa16c | claimTreasuryPayout | 23,116,647 | 18 days agoThu, 30 Jul 2026 06:56:08 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000110 | |
| 0x692040…744f90 | convertFees | 23,116,623 | 18 days agoThu, 30 Jul 2026 06:56:06 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000363 | |
| 0xe18434…fb2665 | claimTreasuryPayout | 22,710,926 | 18 days agoWed, 29 Jul 2026 19:38:08 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000121 | |
| 0x60797d…e9449d | convertFees | 22,710,902 | 18 days agoWed, 29 Jul 2026 19:38:06 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000392 | |
| 0xab8f9b…7be4c6 | claimFallbackPayout | 22,692,602 | 18 days agoWed, 29 Jul 2026 19:07:33 UTC | 0x9e21…1ce0 | IN | HoodlumPadHook | $0.000 ETH | 0.00000132 | |
| 0xf6992b…23aa95 | claimTreasuryPayout | 22,494,670 | 19 days agoWed, 29 Jul 2026 13:37:08 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000128 | |
| 0x8544e7…315a70 | convertFees | 22,494,646 | 19 days agoWed, 29 Jul 2026 13:37:06 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000414 | |
| 0x4a4b85…909668 | claimTreasuryPayout | 22,172,585 | 19 days agoWed, 29 Jul 2026 04:38:09 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000146 | |
| 0x7e3874…93a5de | convertFees | 22,172,561 | 19 days agoWed, 29 Jul 2026 04:38:07 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000483 | |
| 0x3fb030…ed0bcb | claimTreasuryPayout | 22,107,374 | 19 days agoWed, 29 Jul 2026 02:49:10 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000150 | |
| 0x7199ca…12c7da | convertFees | 22,107,350 | 19 days agoWed, 29 Jul 2026 02:49:07 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000496 | |
| 0x4078af…d37742 | claimTreasuryPayout | 22,084,047 | 19 days agoWed, 29 Jul 2026 02:10:11 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000152 | |
| 0xfa4548…28548c | convertFees | 22,084,023 | 19 days agoWed, 29 Jul 2026 02:10:09 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000512 | |
| 0xd1ecde…7d9442 | claimTreasuryPayout | 21,956,281 | 19 days agoTue, 28 Jul 2026 22:37:09 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000151 | |
| 0x1896a5…14ce73 | convertFees | 21,956,257 | 19 days agoTue, 28 Jul 2026 22:37:07 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000540 | |
| 0xe08ff3…792bf5 | claimTreasuryPayout | 21,892,174 | 19 days agoTue, 28 Jul 2026 20:50:11 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000151 | |
| 0xe0d3c4…4c3c50 | convertFees | 21,892,150 | 19 days agoTue, 28 Jul 2026 20:50:08 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000502 | |
| 0x176fc5…ec0a0f | claimTreasuryPayout | 21,873,621 | 19 days agoTue, 28 Jul 2026 20:19:10 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000152 | |
| 0x7ee901…6919f9 | convertFees | 21,873,598 | 19 days agoTue, 28 Jul 2026 20:19:08 UTC | 0xa9b8…233a | IN | HoodlumPadHook | $0.000 ETH | 0.00000505 |
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x78d83017…67bf88 | Transfer | 34,122,981 | 5 days agoWed, 12 Aug 2026 01:15:09 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000237 WETH | WETH (WETH) | |
| 0x3812fbda…b83b1b | Transfer | 34,122,958 | 5 days agoWed, 12 Aug 2026 01:15:06 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.000474 WETH | WETH (WETH) | |
| 0x9e18336b…6d21c4 | Transfer | 23,445,036 | 18 days agoThu, 30 Jul 2026 16:05:05 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000000 WETH | WETH (WETH) | |
| 0x1c97b974…0b2c81 | Transfer | 23,445,012 | 18 days agoThu, 30 Jul 2026 16:05:03 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.000001 WETH | WETH (WETH) | |
| 0x9b41aba1…5077bd | Transfer | 23,439,064 | 18 days agoThu, 30 Jul 2026 15:55:07 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000001 WETH | WETH (WETH) | |
| 0x14d9dd46…27b16f | Transfer | 23,439,040 | 18 days agoThu, 30 Jul 2026 15:55:05 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.000002 WETH | WETH (WETH) | |
| 0x495b6838…6fa16c | Transfer | 23,116,647 | 18 days agoThu, 30 Jul 2026 06:56:08 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000003 WETH | WETH (WETH) | |
| 0x69204044…744f90 | Transfer | 23,116,623 | 18 days agoThu, 30 Jul 2026 06:56:06 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.000007 WETH | WETH (WETH) | |
| 0xe1843403…fb2665 | Transfer | 22,710,926 | 18 days agoWed, 29 Jul 2026 19:38:08 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000000 WETH | WETH (WETH) | |
| 0x60797d32…e9449d | Transfer | 22,710,902 | 18 days agoWed, 29 Jul 2026 19:38:06 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.000000 WETH | WETH (WETH) | |
| 0xab8f9b83…7be4c6 | Transfer | 22,692,602 | 18 days agoWed, 29 Jul 2026 19:07:33 UTC | 0x5a16…b8cc | OUT | 0x9e21…1ce0 | 0.005481 WETH | WETH (WETH) | |
| 0xf6992bbf…23aa95 | Transfer | 22,494,670 | 19 days agoWed, 29 Jul 2026 13:37:08 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000133 WETH | WETH (WETH) | |
| 0x8544e750…315a70 | Transfer | 22,494,646 | 19 days agoWed, 29 Jul 2026 13:37:06 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.000266 WETH | WETH (WETH) | |
| 0x4a4b85ec…909668 | Transfer | 22,172,585 | 19 days agoWed, 29 Jul 2026 04:38:09 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000006 WETH | WETH (WETH) | |
| 0x7e387485…93a5de | Transfer | 22,172,561 | 19 days agoWed, 29 Jul 2026 04:38:07 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.000012 WETH | WETH (WETH) | |
| 0x3fb03041…ed0bcb | Transfer | 22,107,374 | 19 days agoWed, 29 Jul 2026 02:49:10 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000757 WETH | WETH (WETH) | |
| 0x7199ca0e…12c7da | Transfer | 22,107,350 | 19 days agoWed, 29 Jul 2026 02:49:07 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.001514 WETH | WETH (WETH) | |
| 0x4078af39…d37742 | Transfer | 22,084,047 | 19 days agoWed, 29 Jul 2026 02:10:11 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.001359 WETH | WETH (WETH) | |
| 0xfa454810…28548c | Transfer | 22,084,023 | 19 days agoWed, 29 Jul 2026 02:10:09 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.002719 WETH | WETH (WETH) | |
| 0xd1ecde2f…7d9442 | Transfer | 21,956,281 | 19 days agoTue, 28 Jul 2026 22:37:09 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000161 WETH | WETH (WETH) | |
| 0x1896a54f…14ce73 | Transfer | 21,956,257 | 19 days agoTue, 28 Jul 2026 22:37:07 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.000322 WETH | WETH (WETH) | |
| 0xe08ff3bc…792bf5 | Transfer | 21,892,174 | 19 days agoTue, 28 Jul 2026 20:50:11 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000679 WETH | WETH (WETH) | |
| 0xe0d3c405…4c3c50 | Transfer | 21,892,150 | 19 days agoTue, 28 Jul 2026 20:50:08 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.001358 WETH | WETH (WETH) | |
| 0x176fc5dd…ec0a0f | Transfer | 21,873,621 | 19 days agoTue, 28 Jul 2026 20:19:10 UTC | 0x5a16…b8cc | OUT | 0x561d…1f4a | 0.000824 WETH | WETH (WETH) | |
| 0x7ee901f4…6919f9 | Transfer | 21,873,598 | 19 days agoTue, 28 Jul 2026 20:19:08 UTC | 0x8366…0951 | IN | 0x5a16…b8cc | 0.001648 WETH | WETH (WETH) |
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 19,889,593 | 22 days agoSun, 26 Jul 2026 13:00:06 UTC | 0x63bf28…104a5a | CREATE2 | optimized_routeFill921336808 | 0x4e59…956c | IN | 0x5a16…b8cc | 0 ETH |