| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| no token holdings | ||||
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| no token transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x5d9207…0110f7 | 28 days agoMon, 20 Jul 2026 19:59:45 UTC | 0xc7f505…81d2 | data: 0x000000000000000000…ffffffff |
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| No direct transactions — this address is only ever reached via internal calls (common for a contract only invoked through a router or proxy). View Internal Transactions → | |||||||||
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;
import {Initializable} from "openzeppelin-contracts/contracts/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {IERC20Permit} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {Math} from "openzeppelin-contracts/contracts/utils/math/Math.sol";
import {CircusToken} from "./CircusToken.sol";
import {IWETH} from "../interfaces/IWETH.sol";
import {IUniswapV3Pool, INonfungiblePositionManager} from "../interfaces/IUniswapV3.sol";
interface ICircusLocker {
function register(
address token,
uint256 tokenId,
address creator,
address protocol,
uint16 splitBps,
uint16 compoundBps,
address token0,
address token1
) external;
// Immutable wiring, asserted by setInfra so a repoint can't bind new tokens to an incompatible locker.
function launchpad() external view returns (address);
function nfpm() external view returns (address);
function weth() external view returns (address);
}
/// @title CircusLaunchpad
/// @notice Bonding-curve launchpad for Robinhood Chain. A fixed-supply token is sold on an internal
/// constant-product curve with virtual reserves (native ETH), non-transferable until it
/// graduates; on sell-out it migrates into a locked two-sided Uniswap V3 1% pool.
/// UUPS-upgradeable, owned by an admin (a multisig — ownership is a plain address; no
/// timelock, so upgrades/config changes take effect immediately).
///
/// This contract is the full curve lifecycle: create / buy / sell / fee accrual / graduation /
/// migration. The graduated LP position is held forever by the immutable CircusLocker.
///
/// Design highlights: a decaying, buys-only snipe fee (a percentage can't be dodged by
/// splitting wallets, unlike per-wallet caps); all fees owner-configurable but snapshotted
/// immutably per token at creation; per-token infra snapshots so admin config changes never
/// touch already-launched tokens; predictable, un-frontrunnable CREATE2 token addresses with
/// an opt-in vanity suffix asserted on-chain; upgrades gated by the admin owner (two-step
/// handoff via pendingOwner).
contract CircusLaunchpad is Initializable, UUPSUpgradeable {
using SafeERC20 for IERC20;
uint256 internal constant BPS = 10_000;
uint24 public constant LP_FEE = 10_000; // Uniswap V3 1% tier for the graduated pool
// full-range ticks for the 1% tier (tickSpacing 200): floor(±887272 / 200) * 200
int24 internal constant MIN_TICK = -887200;
int24 internal constant MAX_TICK = 887200;
// unique transient slot for the reentrancy guard
uint256 private constant _GUARD = 0xc12c00000000000000000000000000000000000000000000000000000000600d;
// transient slot holding the pool being price-corrected during migrate(); authorizes
// uniswapV3SwapCallback for exactly that one pool.swap call
uint256 private constant _CB_POOL = 0xc12c00000000000000000000000000000000000000000000000000000000600e;
/*//////////////////////////////////////////////////////////////////////
TYPES
//////////////////////////////////////////////////////////////////////*/
/// @notice All fees are ETH-denominated. `*SplitBps` is the CREATOR's share (in bps); the protocol
/// receives the remainder. Snapshotted per token at creation and immutable thereafter.
struct FeeConfig {
uint128 launchFeeWei; // flat fee to create a token
uint16 launchSplitBps; // creator share of the launch fee (usually 0)
uint16 sniperStartBps; // snipe fee at t0, decays linearly to 0 over sniperWindow
uint32 sniperWindow; // snipe-fee duration in seconds (block.timestamp — verified L2 wall-clock)
uint16 sniperSplitBps; // creator share of the snipe fee
uint16 curveTradeBps; // per curve buy/sell, on the ETH leg
uint16 curveSplitBps; // creator share of the curve trade fee
uint128 graduationFlatWei; // flat fee taken from the raise at graduation
uint16 graduationBps; // + % of the raise at graduation
uint16 graduationSplitBps; // creator share of the graduation fee
// Post-graduation V3 swap fees (harvested by the locker) are split in two steps:
// 1. `lpCompoundBps` of each side is reinvested into the locked LP position (compounding);
// 2. the remainder is split creator/protocol by `lpSplitBps` (creator's share of the remainder).
// e.g. lpCompoundBps = 2000, lpSplitBps = 7500 → 20% LP / 60% creator / 20% protocol.
// Appended at the FeeConfig tail so this stays within the struct's existing 2 storage slots
// (a UUPS-safe layout change): pre-upgrade tokens read zero here → no compounding, old behavior.
uint16 lpSplitBps; // creator share of the post-graduation V3 swap fees AFTER compounding
uint16 lpCompoundBps; // share of post-graduation V3 swap fees reinvested into the locked LP
}
struct CurveConfig {
uint128 virtualEth; // virtual ETH reserve seed (e.g. 2.81e18)
uint256 virtualTokens; // virtual token reserve seed
uint256 curveSupply; // tokens sold on the curve (e.g. 800M e18)
uint256 lpSupply; // tokens reserved to seed the V3 pool at graduation (e.g. 200M e18)
}
struct TokenInfo {
address creator;
uint64 createdAt;
bool graduated;
bool migrated;
uint256 ethIn; // real ETH collected into the curve reserve; zeroed at migrate()
uint256 tokensSold; // of curveSupply
uint256 creatorFeesEth; // accrued, claimable by the creator
FeeConfig fee; // snapshot
CurveConfig curve; // snapshot
// Infra snapshot taken at creation: migration runs against the infra the token launched
// under, so the owner can never repoint an already-launched token's WETH,
// position manager, or locker via setInfra — that only affects FUTURE tokens. Appended to the
// struct tail: pre-upgrade tokens read zero here and fall back to the globals (`_infra`).
address weth; // snapshot
address nfpm; // snapshot
address locker; // snapshot
}
/*//////////////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////////////*/
address public owner; // admin (multisig); two-step handoff via pendingOwner
address public protocol; // protocol fee recipient
address public weth;
// Deprecated: was `v3Factory` / `swapRouter` (no longer read — migration talks to the pool
// directly). Kept as reserved slots so the proxy's storage layout is unchanged for in-place upgrades.
address private _deprecatedV3Factory;
address public nfpm; // Uniswap V3 NonfungiblePositionManager
address private _deprecatedSwapRouter;
address public locker; // immutable CircusLocker
FeeConfig internal defaultFee;
CurveConfig internal defaultCurve;
bool public vanityEnforced; // admin override: when true, EVERY token must carry `vanitySuffix`
uint16 public vanitySuffix; // the vanity low 16 bits (4 hex chars) creators grind toward / are asserted against
mapping(address => TokenInfo) internal tokens;
address[] public allTokens;
uint256 public protocolFeesEth;
address public pendingOwner; // two-step ownership: set by transferOwnership, claimed by acceptOwnership
/// @dev Reserve slots for append-only storage growth across UUPS upgrades (one consumed by
/// `pendingOwner`; original reservation was 50).
uint256[49] private __gap;
/*//////////////////////////////////////////////////////////////////////
EVENTS / ERRORS
//////////////////////////////////////////////////////////////////////*/
event Created(
address indexed token,
address indexed creator,
string name,
string symbol,
string tokenURI,
bytes32 salt
);
event Buy(address indexed token, address indexed buyer, uint256 ethIn, uint256 tokensOut, uint256 fee);
event Sell(address indexed token, address indexed seller, uint256 tokensIn, uint256 ethOut, uint256 fee);
event Graduated(address indexed token, uint256 ethRaised);
event Migrated(address indexed token, uint256 indexed tokenId, uint256 ethToLp, uint256 tokensToLp);
event PriceCorrected(address indexed token, address indexed pool, uint256 amountIn, uint256 amountOut);
event CreatorFeesClaimed(address indexed token, address indexed creator, uint256 amount);
event ProtocolFeesFlushed(uint256 amount);
event OwnershipTransferStarted(address indexed from, address indexed to);
event OwnershipTransferred(address indexed from, address indexed to);
event ConfigUpdated();
error NotOwner();
error NotPendingOwner();
error NotCreator();
error ZeroAddress();
error InfraNotSet();
error InvalidFeeConfig();
error InvalidCurveConfig();
error InvalidGraduationConfig();
error InfraMismatch();
error UnknownToken();
error AlreadyGraduated();
error NotGraduated();
error AlreadyMigrated();
error PriceCorrectionFailed();
error SqrtPriceOutOfBounds();
error UnauthorizedCallback();
error VanityMismatch();
error Slippage();
error InsufficientLaunchFee();
error NativeSendFailed();
error ZeroAmount();
error ReserveUnderflow();
modifier onlyOwner() {
if (msg.sender != owner) revert NotOwner();
_;
}
modifier nonReentrant() {
assembly {
if tload(_GUARD) { revert(0, 0) }
tstore(_GUARD, 1)
}
_;
assembly {
tstore(_GUARD, 0)
}
}
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/// @dev `locker_` may be zero here: the locker's constructor needs the launchpad address, so the
/// deploy flow is initialize(locker = 0) → deploy locker → setInfra. Token creation is blocked
/// (`InfraNotSet`) until the locker is wired.
function initialize(
address owner_,
address protocol_,
address weth_,
address nfpm_,
address locker_,
FeeConfig calldata fee_,
CurveConfig calldata curve_,
bool vanityEnforced_,
uint16 vanitySuffix_
) external initializer {
if (owner_ == address(0) || protocol_ == address(0) || weth_ == address(0) || nfpm_ == address(0)) {
revert ZeroAddress();
}
_validateFee(fee_);
_validateCurve(curve_);
_validateGraduation(fee_, curve_);
// The deploy flow initializes with locker == 0 (the locker's constructor needs this address),
// then wires it via setInfra; only assert consistency when a locker is provided up front.
if (locker_ != address(0)) _requireLockerMatches(weth_, nfpm_, locker_);
owner = owner_;
protocol = protocol_;
weth = weth_;
nfpm = nfpm_;
locker = locker_;
defaultFee = fee_;
defaultCurve = curve_;
vanityEnforced = vanityEnforced_;
vanitySuffix = vanitySuffix_;
emit OwnershipTransferred(address(0), owner_);
}
/*//////////////////////////////////////////////////////////////////////
CREATE
//////////////////////////////////////////////////////////////////////*/
/// @notice Deploy a new curve token (no vanity requirement). Salt is bound to the caller
/// (`keccak256(msg.sender, userSalt)`) so the address is predictable + un-frontrunnable.
/// Backward-compatible 5-arg entrypoint: equivalent to `createToken(..., vanity=false)`, so
/// the vanity suffix is skipped unless the admin forces it globally (`vanityEnforced`). Any
/// `msg.value` above the launch fee becomes an optional atomic dev-buy (snipe-fee-exempt).
function createToken(
string calldata name,
string calldata symbol,
string calldata tokenURI,
bytes32 userSalt,
uint256 minDevBuyOut
) external payable nonReentrant returns (address token) {
return _createToken(name, symbol, tokenURI, userSalt, minDevBuyOut, false);
}
/// @notice Deploy a new curve token, opting into the vanity suffix. With `vanity = true`, grind
/// `userSalt` off-chain so the address ends in `vanitySuffix` and the launchpad asserts it;
/// `vanity = false` is identical to the 5-arg overload. The admin can force the suffix on
/// every token regardless via `vanityEnforced`.
function createToken(
string calldata name,
string calldata symbol,
string calldata tokenURI,
bytes32 userSalt,
uint256 minDevBuyOut,
bool vanity
) external payable nonReentrant returns (address token) {
return _createToken(name, symbol, tokenURI, userSalt, minDevBuyOut, vanity);
}
function _createToken(
string calldata name,
string calldata symbol,
string calldata tokenURI,
bytes32 userSalt,
uint256 minDevBuyOut,
bool vanity
) internal returns (address token) {
FeeConfig memory fee = defaultFee;
CurveConfig memory curve = defaultCurve;
if (msg.value < fee.launchFeeWei) revert InsufficientLaunchFee();
bytes32 salt = keccak256(abi.encode(msg.sender, userSalt));
token = address(
new CircusToken{salt: salt}(name, symbol, address(this), curve.curveSupply + curve.lpSupply)
);
// suffix required when the creator opts in (`vanity`) or the admin forces it globally
if ((vanityEnforced || vanity) && uint16(uint160(token)) != vanitySuffix) revert VanityMismatch();
// Set the creator + initial metadata URI on the token (one-shot, same tx). tokenURI is an
// opaque string on-chain (conventionally an https/ipfs pointer); the creator can later edit it
// via setTokenURI/setContractURI. Also emitted in `Created` below as the immutable launch record.
CircusToken(token).initMetadata(msg.sender, tokenURI);
TokenInfo storage t = tokens[token];
t.creator = msg.sender;
t.createdAt = uint64(block.timestamp);
t.fee = fee;
t.curve = curve;
// infra snapshot: this token migrates against the infra it launched under, immutably
if (locker == address(0)) revert InfraNotSet();
t.weth = weth;
t.nfpm = nfpm;
t.locker = locker;
allTokens.push(token);
// launch fee (flat; NOTE: launch fee is a flat wei value, not bps — bps has no base at creation)
_accrue(t, fee.launchFeeWei, fee.launchSplitBps);
emit Created(token, msg.sender, name, symbol, tokenURI, salt);
// optional atomic dev-buy with the remainder, exempt from the snipe fee
uint256 devEth = msg.value - fee.launchFeeWei;
if (devEth > 0) _buyInternal(token, t, msg.sender, devEth, minDevBuyOut, true);
}
/*//////////////////////////////////////////////////////////////////////
BUY / SELL
//////////////////////////////////////////////////////////////////////*/
function buy(address token, uint256 minTokensOut)
external
payable
nonReentrant
returns (uint256 tokensOut)
{
TokenInfo storage t = tokens[token];
if (t.creator == address(0)) revert UnknownToken();
if (t.graduated) revert AlreadyGraduated();
if (msg.value == 0) revert ZeroAmount();
tokensOut = _buyInternal(token, t, msg.sender, msg.value, minTokensOut, false);
}
function _buyInternal(
address token,
TokenInfo storage t,
address buyer,
uint256 gross,
uint256 minOut,
bool exemptSniper
) internal returns (uint256 tokensOut) {
uint256 curveFee = Math.mulDiv(gross, t.fee.curveTradeBps, BPS);
uint256 sniperFee = exemptSniper ? 0 : Math.mulDiv(gross, _sniperBps(t), BPS);
uint256 ethForCurve = gross - curveFee - sniperFee;
uint256 x = uint256(t.curve.virtualEth) + t.ethIn;
uint256 y = t.curve.virtualTokens - t.tokensSold;
uint256 k = uint256(t.curve.virtualEth) * t.curve.virtualTokens;
// tokens out, rounded DOWN (favor the curve): dy = y - ceil(k / (x + ethForCurve))
uint256 dy = y - Math.ceilDiv(k, x + ethForCurve);
uint256 remaining = t.curve.curveSupply - t.tokensSold;
uint256 refund;
if (dy > remaining) {
dy = remaining;
// exact ETH needed to buy `remaining`: newX = ceil(k / (y - remaining)); ethUsed = newX - x
uint256 ethUsed = Math.ceilDiv(k, y - remaining) - x;
// fees are charged only on the ETH the curve actually consumed: scale both legs pro-rata
// and refund the untouched remainder of the gross buy (the graduating buyer no
// longer overpays fees on the refunded portion)
curveFee = Math.mulDiv(curveFee, ethUsed, ethForCurve);
sniperFee = Math.mulDiv(sniperFee, ethUsed, ethForCurve);
refund = gross - ethUsed - curveFee - sniperFee;
ethForCurve = ethUsed;
}
if (dy < minOut) revert Slippage();
t.ethIn += ethForCurve;
t.tokensSold += dy;
_accrue(t, curveFee, t.fee.curveSplitBps);
_accrue(t, sniperFee, t.fee.sniperSplitBps);
bool graduated = t.tokensSold == t.curve.curveSupply;
if (graduated) t.graduated = true;
IERC20(token).safeTransfer(buyer, dy);
if (refund > 0) _sendEth(buyer, refund);
tokensOut = dy;
emit Buy(token, buyer, ethForCurve, dy, curveFee + sniperFee);
if (graduated) emit Graduated(token, t.ethIn);
}
function sell(address token, uint256 tokenAmount, uint256 minEthOut)
external
nonReentrant
returns (uint256)
{
return _sell(token, tokenAmount, minEthOut);
}
/// @notice One-tx sell: EIP-2612-permit the launchpad to pull the tokens, then sell (no approve tx).
/// The permit is best-effort (try/catch) so a front-run/duplicate permit falls back to a
/// standing allowance instead of reverting.
function sellWithPermit(
address token,
uint256 tokenAmount,
uint256 minEthOut,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external nonReentrant returns (uint256) {
try IERC20Permit(token).permit(msg.sender, address(this), tokenAmount, deadline, v, r, s) {} catch {}
return _sell(token, tokenAmount, minEthOut);
}
function _sell(address token, uint256 tokenAmount, uint256 minEthOut) internal returns (uint256 ethOut) {
TokenInfo storage t = tokens[token];
if (t.creator == address(0)) revert UnknownToken();
if (t.graduated) revert AlreadyGraduated();
if (tokenAmount == 0) revert ZeroAmount();
IERC20(token).safeTransferFrom(msg.sender, address(this), tokenAmount);
uint256 x = uint256(t.curve.virtualEth) + t.ethIn;
uint256 y = t.curve.virtualTokens - t.tokensSold;
uint256 k = uint256(t.curve.virtualEth) * t.curve.virtualTokens;
// gross ETH out, rounded DOWN (favor the curve): dx = x - ceil(k / (y + tokenAmount))
uint256 dx = x - Math.ceilDiv(k, y + tokenAmount);
if (dx > t.ethIn) revert ReserveUnderflow();
uint256 curveFee = Math.mulDiv(dx, t.fee.curveTradeBps, BPS);
ethOut = dx - curveFee;
if (ethOut < minEthOut) revert Slippage();
t.ethIn -= dx;
t.tokensSold -= tokenAmount;
_accrue(t, curveFee, t.fee.curveSplitBps);
_sendEth(msg.sender, ethOut);
emit Sell(token, msg.sender, tokenAmount, ethOut, curveFee);
}
/*//////////////////////////////////////////////////////////////////////
GRADUATION
//////////////////////////////////////////////////////////////////////*/
/// @notice Permissionless: once graduated, seed a locked two-sided Uniswap V3 1% pool. Takes the
/// graduation fee, wraps the raise to WETH, initializes the pool at the LP-implied price
/// (forcing a pre-existing pool back to it — see `_forcePoolPrice`), mints a full-range
/// position to the immutable locker, and unlocks token transfers.
function migrate(address token) external nonReentrant {
TokenInfo storage t = tokens[token];
if (t.creator == address(0)) revert UnknownToken();
if (!t.graduated) revert NotGraduated();
if (t.migrated) revert AlreadyMigrated();
t.migrated = true;
uint256 raise = t.ethIn;
// Zeroed so the global solvency invariant `balance >= Σ ethIn + protocolFeesEth + Σ
// creatorFeesEth` holds unconditionally — the raise leaves for the LP in this tx.
// curveInfo() derives the frozen graduation-price display from the curve constants instead.
t.ethIn = 0;
uint256 gradFee = uint256(t.fee.graduationFlatWei) + Math.mulDiv(raise, t.fee.graduationBps, BPS);
if (gradFee > raise) gradFee = raise;
_accrue(t, gradFee, t.fee.graduationSplitBps);
uint256 ethForLp = raise - gradFee;
uint256 tokenForLp = t.curve.lpSupply;
// migration runs against the infra snapshotted at creation — setInfra can't repoint it
(address weth_, address nfpm_, address locker_) = _infra(t);
IWETH(weth_).deposit{value: ethForLp}();
(address token0, address token1) = token < weth_ ? (token, weth_) : (weth_, token);
uint160 target =
token < weth_ ? _sqrtPriceX96(tokenForLp, ethForLp) : _sqrtPriceX96(ethForLp, tokenForLp);
INonfungiblePositionManager pm = INonfungiblePositionManager(nfpm_);
address pool = pm.createAndInitializePoolIfNecessary(token0, token1, LP_FEE, target);
// An empty pool's spot price is adversary-writable for free (pre-create + initialize at a
// bogus price, or a zero-liquidity limit swap), so merely *asserting* it here would be a
// permanent-DoS vector trapping the raise. Impose the graduation price instead: a corrective
// swap bounded by `sqrtPriceLimitX96 = target`, then assert. No-op on the happy path (a
// fresh pool was just initialized at `target` above).
(tokenForLp, ethForLp) = _forcePoolPrice(token, pool, token0, token1, target, tokenForLp, ethForLp);
(uint256 amt0, uint256 amt1) = token < weth_ ? (tokenForLp, ethForLp) : (ethForLp, tokenForLp);
IERC20(token).forceApprove(nfpm_, tokenForLp);
IERC20(weth_).forceApprove(nfpm_, ethForLp);
(uint256 tokenId,,,) = pm.mint(
INonfungiblePositionManager.MintParams({
token0: token0,
token1: token1,
fee: LP_FEE,
tickLower: MIN_TICK,
tickUpper: MAX_TICK,
amount0Desired: amt0,
amount1Desired: amt1,
// Mins stay 0 deliberately: the pool price is asserted == target in this same
// nonReentrant tx (in _forcePoolPrice, just above), so nothing can move it before the
// mint — the manipulated-price deposit vector is closed without mins. After a corrective
// swap the amounts ratio no longer matches `target` exactly (and anyone can donate meme
// to the launchpad), so tight mins would only reintroduce a spurious-revert DoS.
// Unconsumed dust strands on the launchpad, as before (outside the solvency invariant).
amount0Min: 0,
amount1Min: 0,
recipient: locker_,
deadline: block.timestamp
})
);
ICircusLocker(locker_)
.register(
token, tokenId, t.creator, protocol, t.fee.lpSplitBps, t.fee.lpCompoundBps, token0, token1
);
CircusToken(token).unlock();
emit Migrated(token, tokenId, ethForLp, tokenForLp);
}
/// @dev Effective infra for a token: the snapshot taken at creation, or the current globals for
/// tokens created before infra snapshotting existed (their snapshot slots read zero after an
/// in-place upgrade). Every token created by this code version has a full snapshot.
function _infra(TokenInfo storage t)
internal
view
returns (address weth_, address nfpm_, address locker_)
{
(weth_, nfpm_, locker_) = (t.weth, t.nfpm, t.locker);
if (weth_ == address(0)) (weth_, nfpm_, locker_) = (weth, nfpm, locker);
}
/// @dev Force the pool's spot price to the graduation price `target` before minting, adjusting
/// the LP amounts by exactly what the corrective swap moved. Invariant: while the token is
/// transfer-locked, no meme-side pool liquidity can exist (nobody but the launchpad can pay meme
/// into the pool), so the swap either slides an empty book to `target` for free (~0 exchanged)
/// or sells meme into donated WETH bids at prices at-or-better-than the graduation price (modulo
/// the 1% LP fee) — never unfavorable.
///
/// Uses a raw `pool.swap` (with the transient-authorized callback below) rather than
/// SwapRouter02: the router refuses swaps that settle entirely inside a zero-liquidity region
/// (`require(amount0Delta > 0 || amount1Delta > 0)`), which is precisely the common griefed
/// case — an empty pool whose price was teleported.
function _forcePoolPrice(
address token,
address pool,
address token0,
address token1,
uint160 target,
uint256 tokenForLp,
uint256 ethForLp
) internal returns (uint256, uint256) {
(uint160 poolSqrt,,,,,,) = IUniswapV3Pool(pool).slot0();
if (poolSqrt == target) return (tokenForLp, ethForLp);
// Selling token0 moves sqrtPrice down, selling token1 moves it up. Cap the input at everything
// we hold on that side — the price limit is the real bound: the pool partial-fills and stops
// exactly at `target` (no revert on partial consumption).
bool zeroForOne = poolSqrt > target;
address tokenIn = zeroForOne ? token0 : token1;
uint256 cap = tokenIn == token ? tokenForLp : ethForLp;
assembly {
tstore(_CB_POOL, pool)
}
(int256 d0, int256 d1) = IUniswapV3Pool(pool)
.swap(address(this), zeroForOne, int256(cap), target, abi.encode(token0, token1));
assembly {
tstore(_CB_POOL, 0)
}
// Adjust the mint amounts by the pool-accounted swap deltas (positive = we paid, negative = we
// received) — never by raw balanceOf, which donations to the launchpad could skew.
(uint256 spent, uint256 out) = zeroForOne ? (uint256(d0), uint256(-d1)) : (uint256(d1), uint256(-d0));
if (tokenIn == token) {
tokenForLp -= spent;
ethForLp += out;
} else {
ethForLp -= spent;
tokenForLp += out;
}
// Reachable only if an attacker walled off `target` behind more real WETH bids (at/above the
// graduation price) than our whole cap chews through — an "attack" that pays us. The revert
// unwinds `t.migrated`, and migrate() is permissionless, so anyone can retry after taking the
// attacker's money.
(poolSqrt,,,,,,) = IUniswapV3Pool(pool).slot0();
if (poolSqrt != target) revert PriceCorrectionFailed();
emit PriceCorrected(token, pool, spent, out);
return (tokenForLp, ethForLp);
}
/// @notice Uniswap V3 swap callback: pays the pool for the corrective swap in `_forcePoolPrice`.
/// Authorized by the transient slot holding that exact pool address for the duration of the
/// single `pool.swap` call — any other caller or timing reverts. The claimed deltas are
/// trusted because the pool came from the canonical factory in the same transaction.
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external {
address expected;
assembly {
expected := tload(_CB_POOL)
}
if (expected == address(0) || msg.sender != expected) revert UnauthorizedCallback();
(address token0, address token1) = abi.decode(data, (address, address));
if (amount0Delta > 0) IERC20(token0).safeTransfer(msg.sender, uint256(amount0Delta));
if (amount1Delta > 0) IERC20(token1).safeTransfer(msg.sender, uint256(amount1Delta));
}
/// @dev sqrtPriceX96 = sqrt(amt1 / amt0) * 2^96, computed as sqrt(amt1 * 2^192 / amt0) with 512-bit
/// intermediates (Math.mulDiv) to avoid overflow. Bounded strictly inside TickMath's
/// [MIN_SQRT_RATIO, MAX_SQRT_RATIO] so a pathological curve config fails loudly here rather than
/// deep inside the pool — and so the result is always a valid `sqrtPriceLimitX96` for the
/// corrective swap in either direction. Never triggers with the shipped config.
function _sqrtPriceX96(uint256 amt0, uint256 amt1) internal pure returns (uint160) {
uint256 ratioX192 = Math.mulDiv(amt1, uint256(1) << 192, amt0);
uint256 s = Math.sqrt(ratioX192);
// TickMath.MIN_SQRT_RATIO / MAX_SQRT_RATIO, inlined (the upper bound also covers the uint160 cast)
if (s <= 4295128739 || s >= 1461446703485210103287273052203988822378723970342) {
revert SqrtPriceOutOfBounds();
}
return uint160(s);
}
/*//////////////////////////////////////////////////////////////////////
FEES
//////////////////////////////////////////////////////////////////////*/
function _accrue(TokenInfo storage t, uint256 amount, uint16 creatorSplitBps) internal {
if (amount == 0) return;
uint256 creatorCut = Math.mulDiv(amount, creatorSplitBps, BPS);
t.creatorFeesEth += creatorCut;
protocolFeesEth += amount - creatorCut;
}
/// @notice Current snipe-fee rate (bps), decaying linearly from `sniperStartBps` to 0 over the window.
function _sniperBps(TokenInfo storage t) internal view returns (uint256) {
uint256 window = t.fee.sniperWindow;
if (window == 0) return 0;
uint256 elapsed = block.timestamp - t.createdAt;
if (elapsed >= window) return 0;
uint256 start = t.fee.sniperStartBps;
return start - (start * elapsed) / window;
}
function currentSniperBps(address token) external view returns (uint256) {
return _sniperBps(tokens[token]);
}
function claimCreatorFees(address token) external nonReentrant returns (uint256 amount) {
TokenInfo storage t = tokens[token];
if (msg.sender != t.creator) revert NotCreator();
amount = t.creatorFeesEth;
t.creatorFeesEth = 0;
if (amount > 0) _sendEth(msg.sender, amount);
emit CreatorFeesClaimed(token, msg.sender, amount);
}
/// @notice Permissionless flush of accrued protocol fees to the protocol recipient.
function flushProtocolFees() external nonReentrant returns (uint256 amount) {
amount = protocolFeesEth;
protocolFeesEth = 0;
if (amount > 0) _sendEth(protocol, amount);
emit ProtocolFeesFlushed(amount);
}
/*//////////////////////////////////////////////////////////////////////
VIEWS
//////////////////////////////////////////////////////////////////////*/
function tokenCount() external view returns (uint256) {
return allTokens.length;
}
/// @notice Scalar per-token state (the nested-struct fields are read via the `tokens` getter).
function tokenState(address token)
external
view
returns (
address creator,
bool graduated,
bool migrated,
uint256 ethIn,
uint256 tokensSold,
uint256 creatorFeesEth
)
{
TokenInfo storage t = tokens[token];
return (t.creator, t.graduated, t.migrated, t.ethIn, t.tokensSold, t.creatorFeesEth);
}
/// @notice Off-chain helper: tokens out for `ethIn` on the curve right now (net of fees, incl. snipe).
function quoteBuy(address token, uint256 ethIn) external view returns (uint256 tokensOut) {
TokenInfo storage t = tokens[token];
if (t.creator == address(0) || t.graduated || ethIn == 0) return 0;
uint256 fees = Math.mulDiv(ethIn, t.fee.curveTradeBps, BPS) + Math.mulDiv(ethIn, _sniperBps(t), BPS);
uint256 ethForCurve = ethIn - fees;
uint256 x = uint256(t.curve.virtualEth) + t.ethIn;
uint256 y = t.curve.virtualTokens - t.tokensSold;
uint256 k = uint256(t.curve.virtualEth) * t.curve.virtualTokens;
uint256 dy = y - Math.ceilDiv(k, x + ethForCurve);
uint256 remaining = t.curve.curveSupply - t.tokensSold;
tokensOut = dy > remaining ? remaining : dy;
}
/// @notice Off-chain helper: ETH out for selling `tokenAmount` on the curve now (net of the curve fee).
function quoteSell(address token, uint256 tokenAmount) external view returns (uint256 ethOut) {
TokenInfo storage t = tokens[token];
if (t.creator == address(0) || t.graduated || tokenAmount == 0) return 0;
uint256 x = uint256(t.curve.virtualEth) + t.ethIn;
uint256 y = t.curve.virtualTokens - t.tokensSold;
uint256 k = uint256(t.curve.virtualEth) * t.curve.virtualTokens;
uint256 dx = x - Math.ceilDiv(k, y + tokenAmount);
if (dx > t.ethIn) return 0;
ethOut = dx - Math.mulDiv(dx, t.fee.curveTradeBps, BPS);
}
/// @notice Effective curve reserves + progress for the indexer/UI. `ethReserve/tokenReserve` are the
/// AMM's x/y (virtual + real); price = ethReserve/tokenReserve. Post-graduation these freeze
/// at the graduation state, so the display price holds at the graduation price. The frozen
/// ETH reserve is DERIVED from the curve constants (a graduating buy always lands x exactly
/// on ceil(k / (Vt - curveSupply))) because `ethIn` is zeroed at migrate() for solvency
/// accounting — the derived value is bit-identical to the retained one, pre- and post-migrate.
function curveInfo(address token)
external
view
returns (
uint256 ethReserve,
uint256 tokenReserve,
uint256 tokensSold,
uint256 curveSupply,
bool graduated,
bool migrated
)
{
TokenInfo storage t = tokens[token];
ethReserve = t.graduated
? Math.ceilDiv(
uint256(t.curve.virtualEth) * t.curve.virtualTokens,
t.curve.virtualTokens - t.curve.curveSupply
)
: uint256(t.curve.virtualEth) + t.ethIn;
tokenReserve = t.curve.virtualTokens - t.tokensSold;
tokensSold = t.tokensSold;
curveSupply = t.curve.curveSupply;
graduated = t.graduated;
migrated = t.migrated;
}
/// @notice The infra a token is bound to migrate against (its creation-time snapshot; globals for
/// tokens created before snapshotting existed).
function tokenInfra(address token) external view returns (address weth_, address nfpm_, address locker_) {
return _infra(tokens[token]);
}
/// @notice Predict a token's address for a `(creator, userSalt)` pair. Frontend grinds `userSalt`
/// so the result ends in `vanitySuffix`; the value is recomputable, so nothing need be stored.
function predictAddress(address creator, bytes32 userSalt, string calldata name, string calldata symbol)
external
view
returns (address predicted)
{
bytes32 salt = keccak256(abi.encode(creator, userSalt));
uint256 supply = defaultCurve.curveSupply + defaultCurve.lpSupply;
bytes32 initCodeHash = keccak256(
abi.encodePacked(type(CircusToken).creationCode, abi.encode(name, symbol, address(this), supply))
);
predicted = address(
uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, initCodeHash))))
);
}
/*//////////////////////////////////////////////////////////////////////
ADMIN
//////////////////////////////////////////////////////////////////////*/
function setDefaultFee(FeeConfig calldata fee_) external onlyOwner {
_validateFee(fee_);
_validateGraduation(fee_, defaultCurve);
defaultFee = fee_;
emit ConfigUpdated();
}
function setDefaultCurve(CurveConfig calldata curve_) external onlyOwner {
_validateCurve(curve_);
_validateGraduation(defaultFee, curve_);
defaultCurve = curve_;
emit ConfigUpdated();
}
/// @dev Configs are validated when SET (initialize / setters), so every per-token snapshot taken in
/// createToken is valid by construction. Bounds guarantee no fee path can underflow or brick:
/// buys keep a positive ETH leg even at t0 with the snipe fee at its start value, and every
/// split fits in BPS (an lpSplitBps > BPS would make the immutable locker's collect underflow).
function _validateFee(FeeConfig calldata f) internal pure {
if (uint256(f.sniperStartBps) + f.curveTradeBps >= BPS) revert InvalidFeeConfig();
if (f.graduationBps > BPS) revert InvalidFeeConfig();
if (
f.launchSplitBps > BPS || f.sniperSplitBps > BPS || f.curveSplitBps > BPS
|| f.graduationSplitBps > BPS || f.lpSplitBps > BPS || f.lpCompoundBps > BPS
) revert InvalidFeeConfig();
}
/// @dev virtualTokens must exceed curveSupply (the curve's token reserve stays positive through
/// sell-out) and fit in 128 bits so k = virtualEth * virtualTokens can't overflow uint256.
function _validateCurve(CurveConfig calldata c) internal pure {
if (c.virtualEth == 0 || c.curveSupply == 0 || c.lpSupply == 0) revert InvalidCurveConfig();
if (c.virtualTokens <= c.curveSupply) revert InvalidCurveConfig();
if (c.virtualTokens > type(uint128).max) revert InvalidCurveConfig();
}
/// @dev Reject fee+curve pairs that would make `migrate` revert and permanently trap a graduated
/// raise (buys/sells are blocked once graduated, so a token that can't migrate is stuck). Run
/// whenever EITHER config is set, against the other's current value, so every per-token snapshot
/// is migrate-safe by construction. Closes two brick conditions:
/// (1) the graduation fee eats the whole raise (`ethForLp == 0`), and
/// (2) the graduation-implied pool price is outside Uniswap's sqrt range, or `lpSupply` is so
/// mismatched to the raise that `_sqrtPriceX96` overflows — either reverts in migrate.
/// Both are evaluated at the *minimum* achievable raise (whole curve sold), which is the worst
/// case: `ethForLp` is smallest there, so the low-side price is lowest and the high-side highest.
/// Callers pass `_validateFee`/`_validateCurve`-checked configs, so `k` can't overflow and
/// `virtualTokens > curveSupply`.
function _validateGraduation(FeeConfig memory f, CurveConfig memory c) internal pure {
// Deterministic floor on the graduation raise: the ETH the curve charges to sell all of
// curveSupply. Curve rounding only ever rounds the real raise UP from this, so it's a true lower
// bound (see the buy math; new reserve is rounded up each trade).
uint256 k = uint256(c.virtualEth) * c.virtualTokens;
uint256 raiseFloor = Math.ceilDiv(k, c.virtualTokens - c.curveSupply) - c.virtualEth;
// ethForLp = raise - gradFee is non-decreasing in raise (graduationBps <= BPS), so if it's
// positive at the floor it's positive for every real raise.
uint256 gradFee = uint256(f.graduationFlatWei) + Math.mulDiv(raiseFloor, f.graduationBps, BPS);
if (gradFee >= raiseFloor) revert InvalidGraduationConfig();
uint256 ethForLpFloor = raiseFloor - gradFee;
// The pool must be seedable at the graduation price in BOTH token orderings (the deployed token
// sorts either side of WETH). `_sqrtPriceX96` reverts if the price is out of range or the ratio
// overflows, so a pair of calls that returns is proof both orderings are migrate-safe.
_sqrtPriceX96(c.lpSupply, ethForLpFloor);
_sqrtPriceX96(ethForLpFloor, c.lpSupply);
}
/// @dev Assert a locker is wired to THIS launchpad and shares the exact nfpm/weth it will be paired
/// with. `migrate` mints the position on the launchpad's snapshotted `nfpm` to the locker and
/// records token0/token1 sorted by the snapshotted `weth`; the locker later collects from its
/// OWN immutable nfpm and classifies sides by its OWN immutable weth. If those diverge, harvest
/// reverts forever (fees unrecoverable in the immutable locker) or misroutes them across the
/// shared escrow ledger. Enforced at every infra wiring so a repoint can't create that divergence.
function _requireLockerMatches(address weth_, address nfpm_, address locker_) internal view {
if (
ICircusLocker(locker_).launchpad() != address(this) || ICircusLocker(locker_).nfpm() != nfpm_
|| ICircusLocker(locker_).weth() != weth_
) revert InfraMismatch();
}
function setProtocol(address protocol_) external onlyOwner {
if (protocol_ == address(0)) revert ZeroAddress();
protocol = protocol_;
emit ConfigUpdated();
}
function setVanity(bool enforced_, uint16 suffix_) external onlyOwner {
vanityEnforced = enforced_;
vanitySuffix = suffix_;
emit ConfigUpdated();
}
/// @notice Set the infra used by tokens created FROM NOW ON. Existing tokens are unaffected — they
/// migrate against the snapshot taken at their creation.
function setInfra(address weth_, address nfpm_, address locker_) external onlyOwner {
if (weth_ == address(0) || nfpm_ == address(0) || locker_ == address(0)) revert ZeroAddress();
_requireLockerMatches(weth_, nfpm_, locker_);
weth = weth_;
nfpm = nfpm_;
locker = locker_;
emit ConfigUpdated();
}
/// @notice Two-step ownership handover: nothing changes until the new owner claims it via
/// acceptOwnership(), so ownership can never be fat-fingered to a dead address.
/// `newOwner = 0` cancels a pending transfer.
function transferOwnership(address newOwner) external onlyOwner {
pendingOwner = newOwner;
emit OwnershipTransferStarted(owner, newOwner);
}
function acceptOwnership() external {
if (msg.sender != pendingOwner) revert NotPendingOwner();
emit OwnershipTransferred(owner, msg.sender);
owner = msg.sender;
pendingOwner = address(0);
}
function _authorizeUpgrade(address) internal override onlyOwner {}
/*//////////////////////////////////////////////////////////////////////
INTERNAL
//////////////////////////////////////////////////////////////////////*/
function _sendEth(address to, uint256 amount) internal {
(bool ok,) = to.call{value: amount}("");
if (!ok) revert NativeSendFailed();
}
}[
{
"type": "constructor",
"inputs": [],
"stateMutability": "nonpayable"
},
{
"name": "AddressEmptyCode",
"type": "error",
"inputs": [
{
"name": "target",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "AlreadyGraduated",
"type": "error",
"inputs": []
},
{
"name": "AlreadyMigrated",
"type": "error",
"inputs": []
},
{
"name": "ERC1967InvalidImplementation",
"type": "error",
"inputs": [
{
"name": "implementation",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ERC1967NonPayable",
"type": "error",
"inputs": []
},
{
"name": "FailedCall",
"type": "error",
"inputs": []
},
{
"name": "InfraMismatch",
"type": "error",
"inputs": []
},
{
"name": "InfraNotSet",
"type": "error",
"inputs": []
},
{
"name": "InsufficientLaunchFee",
"type": "error",
"inputs": []
},
{
"name": "InvalidCurveConfig",
"type": "error",
"inputs": []
},
{
"name": "InvalidFeeConfig",
"type": "error",
"inputs": []
},
{
"name": "InvalidGraduationConfig",
"type": "error",
"inputs": []
},
{
"name": "InvalidInitialization",
"type": "error",
"inputs": []
},
{
"name": "NativeSendFailed",
"type": "error",
"inputs": []
},
{
"name": "NotCreator",
"type": "error",
"inputs": []
},
{
"name": "NotGraduated",
"type": "error",
"inputs": []
},
{
"name": "NotInitializing",
"type": "error",
"inputs": []
},
{
"name": "NotOwner",
"type": "error",
"inputs": []
},
{
"name": "NotPendingOwner",
"type": "error",
"inputs": []
},
{
"name": "PriceCorrectionFailed",
"type": "error",
"inputs": []
},
{
"name": "ReserveUnderflow",
"type": "error",
"inputs": []
},
{
"name": "SafeERC20FailedOperation",
"type": "error",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "Slippage",
"type": "error",
"inputs": []
},
{
"name": "SqrtPriceOutOfBounds",
"type": "error",
"inputs": []
},
{
"name": "UUPSUnauthorizedCallContext",
"type": "error",
"inputs": []
},
{
"name": "UUPSUnsupportedProxiableUUID",
"type": "error",
"inputs": [
{
"name": "slot",
"type": "bytes32",
"internalType": "bytes32"
}
]
},
{
"name": "UnauthorizedCallback",
"type": "error",
"inputs": []
},
{
"name": "UnknownToken",
"type": "error",
"inputs": []
},
{
"name": "VanityMismatch",
"type": "error",
"inputs": []
},
{
"name": "ZeroAddress",
"type": "error",
"inputs": []
},
{
"name": "ZeroAmount",
"type": "error",
"inputs": []
},
{
"name": "Buy",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "buyer",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "ethIn",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "tokensOut",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "fee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "ConfigUpdated",
"type": "event",
"inputs": [],
"anonymous": false
},
{
"name": "Created",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "creator",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "name",
"type": "string",
"indexed": false,
"internalType": "string"
},
{
"name": "symbol",
"type": "string",
"indexed": false,
"internalType": "string"
},
{
"name": "tokenURI",
"type": "string",
"indexed": false,
"internalType": "string"
},
{
"name": "salt",
"type": "bytes32",
"indexed": false,
"internalType": "bytes32"
}
],
"anonymous": false
},
{
"name": "CreatorFeesClaimed",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "creator",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "Graduated",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "ethRaised",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "Initialized",
"type": "event",
"inputs": [
{
"name": "version",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
}
],
"anonymous": false
},
{
"name": "Migrated",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "tokenId",
"type": "uint256",
"indexed": true,
"internalType": "uint256"
},
{
"name": "ethToLp",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "tokensToLp",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "OwnershipTransferStarted",
"type": "event",
"inputs": [
{
"name": "from",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "OwnershipTransferred",
"type": "event",
"inputs": [
{
"name": "from",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "PriceCorrected",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "pool",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amountIn",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "amountOut",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "ProtocolFeesFlushed",
"type": "event",
"inputs": [
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "Sell",
"type": "event",
"inputs": [
{
"name": "token",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "seller",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "tokensIn",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "ethOut",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "fee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "Upgraded",
"type": "event",
"inputs": [
{
"name": "implementation",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "LP_FEE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint24",
"internalType": "uint24"
}
],
"stateMutability": "view"
},
{
"name": "UPGRADE_INTERFACE_VERSION",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"name": "acceptOwnership",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "allTokens",
"type": "function",
"inputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "buy",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "minTokensOut",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "tokensOut",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "payable"
},
{
"name": "claimCreatorFees",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "createToken",
"type": "function",
"inputs": [
{
"name": "name",
"type": "string",
"internalType": "string"
},
{
"name": "symbol",
"type": "string",
"internalType": "string"
},
{
"name": "tokenURI",
"type": "string",
"internalType": "string"
},
{
"name": "userSalt",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "minDevBuyOut",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "payable"
},
{
"name": "createToken",
"type": "function",
"inputs": [
{
"name": "name",
"type": "string",
"internalType": "string"
},
{
"name": "symbol",
"type": "string",
"internalType": "string"
},
{
"name": "tokenURI",
"type": "string",
"internalType": "string"
},
{
"name": "userSalt",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "minDevBuyOut",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "vanity",
"type": "bool",
"internalType": "bool"
}
],
"outputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "payable"
},
{
"name": "currentSniperBps",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "curveInfo",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "ethReserve",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "tokenReserve",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "tokensSold",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "curveSupply",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "graduated",
"type": "bool",
"internalType": "bool"
},
{
"name": "migrated",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "flushProtocolFees",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "initialize",
"type": "function",
"inputs": [
{
"name": "owner_",
"type": "address",
"internalType": "address"
},
{
"name": "protocol_",
"type": "address",
"internalType": "address"
},
{
"name": "weth_",
"type": "address",
"internalType": "address"
},
{
"name": "nfpm_",
"type": "address",
"internalType": "address"
},
{
"name": "locker_",
"type": "address",
"internalType": "address"
},
{
"name": "fee_",
"type": "tuple",
"components": [
{
"name": "launchFeeWei",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "launchSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "sniperStartBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "sniperWindow",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "sniperSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "curveTradeBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "curveSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "graduationFlatWei",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "graduationBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "graduationSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "lpSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "lpCompoundBps",
"type": "uint16",
"internalType": "uint16"
}
],
"internalType": "struct CircusLaunchpad.FeeConfig"
},
{
"name": "curve_",
"type": "tuple",
"components": [
{
"name": "virtualEth",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "virtualTokens",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "curveSupply",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "lpSupply",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct CircusLaunchpad.CurveConfig"
},
{
"name": "vanityEnforced_",
"type": "bool",
"internalType": "bool"
},
{
"name": "vanitySuffix_",
"type": "uint16",
"internalType": "uint16"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "locker",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "migrate",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "nfpm",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "owner",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "pendingOwner",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "predictAddress",
"type": "function",
"inputs": [
{
"name": "creator",
"type": "address",
"internalType": "address"
},
{
"name": "userSalt",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "name",
"type": "string",
"internalType": "string"
},
{
"name": "symbol",
"type": "string",
"internalType": "string"
}
],
"outputs": [
{
"name": "predicted",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "protocol",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "protocolFeesEth",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "proxiableUUID",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "quoteBuy",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "ethIn",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "tokensOut",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "quoteSell",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "tokenAmount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "ethOut",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "sell",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "tokenAmount",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "minEthOut",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "sellWithPermit",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
},
{
"name": "tokenAmount",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "minEthOut",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "deadline",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "v",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "r",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "s",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "setDefaultCurve",
"type": "function",
"inputs": [
{
"name": "curve_",
"type": "tuple",
"components": [
{
"name": "virtualEth",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "virtualTokens",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "curveSupply",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "lpSupply",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct CircusLaunchpad.CurveConfig"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setDefaultFee",
"type": "function",
"inputs": [
{
"name": "fee_",
"type": "tuple",
"components": [
{
"name": "launchFeeWei",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "launchSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "sniperStartBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "sniperWindow",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "sniperSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "curveTradeBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "curveSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "graduationFlatWei",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "graduationBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "graduationSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "lpSplitBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "lpCompoundBps",
"type": "uint16",
"internalType": "uint16"
}
],
"internalType": "struct CircusLaunchpad.FeeConfig"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setInfra",
"type": "function",
"inputs": [
{
"name": "weth_",
"type": "address",
"internalType": "address"
},
{
"name": "nfpm_",
"type": "address",
"internalType": "address"
},
{
"name": "locker_",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setProtocol",
"type": "function",
"inputs": [
{
"name": "protocol_",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "setVanity",
"type": "function",
"inputs": [
{
"name": "enforced_",
"type": "bool",
"internalType": "bool"
},
{
"name": "suffix_",
"type": "uint16",
"internalType": "uint16"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "tokenCount",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "tokenInfra",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "weth_",
"type": "address",
"internalType": "address"
},
{
"name": "nfpm_",
"type": "address",
"internalType": "address"
},
{
"name": "locker_",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "tokenState",
"type": "function",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "creator",
"type": "address",
"internalType": "address"
},
{
"name": "graduated",
"type": "bool",
"internalType": "bool"
},
{
"name": "migrated",
"type": "bool",
"internalType": "bool"
},
{
"name": "ethIn",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "tokensSold",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "creatorFeesEth",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "transferOwnership",
"type": "function",
"inputs": [
{
"name": "newOwner",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "uniswapV3SwapCallback",
"type": "function",
"inputs": [
{
"name": "amount0Delta",
"type": "int256",
"internalType": "int256"
},
{
"name": "amount1Delta",
"type": "int256",
"internalType": "int256"
},
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "upgradeToAndCall",
"type": "function",
"inputs": [
{
"name": "newImplementation",
"type": "address",
"internalType": "address"
},
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [],
"stateMutability": "payable"
},
{
"name": "vanityEnforced",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "vanitySuffix",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "weth",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
}
]0x60a080604052346100c257306080525f5160206160205f395f51905f525460ff8160401c166100b3576002600160401b03196001600160401b03821601610060575b604051615f5990816100c782396080518181816108c501526121a10152f35b6001600160401b0319166001600160401b039081175f5160206160205f395f51905f525581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f80610041565b63f92ee8a960e01b5f5260045ffd5b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80630a9d793d146102845780630d7a94f61461027f57806311a15a3b1461027a57806311c2b76c146102755780631daf62d6146102705780631f31905d1461026b5780633fc8cef3146102665780634bf45e8c146102615780634c33aa2e1461025c5780634f1ef2861461025757806352d1902d1461025257806359b6f0dc1461024d5780635e3f2727146102485780636025d89814610243578063634282af1461023e578063690d3c00146102395780636a272462146102345780637303e9131461022f57806374c5bf221461022a57806379ba50971461022557806379ccb4751461022057806387c1ea7f1461021b5780638ce74426146102165780638da5cb5b14610211578063956b79931461020c5780639f181b5e14610207578063ad3cb1cc14610202578063b3dbac77146101fd578063c03dcecd146101f8578063cce7ec13146101f3578063ce5494bb146101ee578063d6ae6e44146101e9578063d7b96d4e146101e4578063d98b2f5c146101df578063e0c6e7c3146101da578063e30c3978146101d5578063e8965ceb146101d0578063f2fde38b146101cb5763fa461e33146101c6575f80fd5b611bef565b611b78565b611ae9565b611ac1565b611a29565b6119fe565b6119d6565b6118fe565b611341565b611297565b6111c5565b61112f565b6110e8565b6110a7565b611003565b610fcb565b610fa3565b610f81565b610f64565b610eec565b610d71565b610d49565b610ce9565b610a52565b6109e6565b6109c2565b6109a6565b610919565b6108b3565b610837565b6106a4565b61063b565b610613565b61056a565b610503565b610493565b610353565b610320565b61029e565b6001600160a01b0381160361029a57565b5f80fd5b3461029a57602036600319011261029a576004356102bb81610289565b5f546001600160a01b03163303610311576001600160a01b0316801561030257600180546001600160a01b0319169190911790555f516020615ee45f395f51905f525f80a1005b63d92e233d60e01b5f5260045ffd5b6330cd747160e01b5f5260045ffd5b3461029a57604036600319011261029a57602061034b60043561034281610289565b60243590611d2f565b604051908152f35b3461029a57602036600319011261029a5760043561037081610289565b6001600160a01b03165f908152600e60205260409020805461044060e082901c60ff169182156104445760068401546103e1906103bd906001600160801b03165b6001600160801b031690565b6103db6103cf60078801548093611d1c565b91600888015490611d0f565b90612e7c565b925b60078501549161040a60086103fd60028901548096611d0f565b9701549160e81c60ff1690565b926040519687968794919260a0949197969360c08701988752602087015260408601526060850152151560808401521515910152565b0390f35b600684015461046a9061045f906001600160801b03166103b1565b600186015490611cfd565b926103e3565b8015150361029a57565b61ffff81160361029a57565b35906104918261047a565b565b3461029a57604036600319011261029a576004356104b081610470565b6024356104bc8161047a565b5f546001600160a01b0316330361031157600d805462ffffff191692151560ff169290921760089190911b62ffff00161790555b5f516020615ee45f395f51905f525f80a1005b3461029a57602036600319011261029a5760043561052081610289565b60018060a01b03165f52600e602052602061034b60405f20612e19565b9181601f8401121561029a578235916001600160401b03831161029a576020838186019501011161029a57565b60a036600319011261029a576004356001600160401b03811161029a5761059590369060040161053d565b906024356001600160401b03811161029a576105b590369060040161053d565b919092604435926001600160401b03841161029a57610440946105df6105ef95369060040161053d565b9290916064359460843596611e32565b6040516001600160a01b0390911681529081906020820190565b5f91031261029a57565b3461029a575f36600319011261029a576002546040516001600160a01b039091168152602090f35b3461029a57602036600319011261029a5760043561065881610289565b60018060a01b03165f52600e602052606061067560405f2061314f565b604080516001600160a01b0394851681529284166020840152921691810191909152f35b60ff81160361029a57565b3461029a5760e036600319011261029a576004356106c181610289565b60243560443560643591608435936106d885610699565b60a43560c4359561600d61304b60f21b015c61029a57600161600d61304b60f21b015d6001600160a01b03831690813b1561029a5760e4610763975f80946104409b60ff97604051988997889663d505accf60e01b88523360048901523060248901528d6044890152606488015216608486015260a485015260c48401525af161077f575b5061319a565b5f61600d61304b60f21b015d6040519081529081906020820190565b8061078d5f610793936107cd565b80610609565b5f61075d565b634e487b7160e01b5f52604160045260245ffd5b608081019081106001600160401b038211176107c857604052565b610799565b90601f801991011681019081106001600160401b038211176107c857604052565b60405190610491610160836107cd565b60405190610491610180836107cd565b9061049160405192836107cd565b6001600160401b0381116107c857601f01601f191660200190565b604036600319011261029a5760043561084f81610289565b602435906001600160401b03821161029a573660238301121561029a5781600401359061087b8261081c565b9161088960405193846107cd565b808352366024828601011161029a576020815f9260246108b197018387013784010152612195565b005b3461029a575f36600319011261029a577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316300361090a5760206040515f516020615ec45f395f51905f528152f35b63703e46dd60e11b5f5260045ffd5b3461029a57602036600319011261029a5760043561093681610289565b6001600160a01b039081165f908152600e60209081526040918290208054600182015460028301546003909301548551968316875260ff60e084901c811615159588019590955260e89290921c9093161515938501939093526060840191909152608083015260a082015260c090f35b3461029a575f36600319011261029a5760206040516127108152f35b3461029a575f36600319011261029a57602061ffff600d5460081c16604051908152f35b3461029a57602036600319011261029a57600435600f5481101561029a57600f5f527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac80201546040516001600160a01b039091168152602090f35b61018090600319011261029a57600490565b3461029a5761018036600319011261029a57610a6d36610a40565b5f546001600160a01b0316330361031157610cc861016082610a916104f094613320565b610aac610a9e36836122e8565b610aa66123cd565b90613439565b610ada610ab882612402565b600780546001600160801b0319166001600160801b0392909216919091179055565b610b0a610ae96020830161240f565b6007805461ffff60801b191660809290921b61ffff60801b16919091179055565b610b3a610b196040830161240f565b6007805461ffff60901b191660909290921b61ffff60901b16919091179055565b610b6e610b4960608301612457565b6007805463ffffffff60a01b191660a09290921b63ffffffff60a01b16919091179055565b610b9e610b7d6080830161240f565b6007805461ffff60c01b191660c09290921b61ffff60c01b16919091179055565b610bce610bad60a0830161240f565b6007805461ffff60d01b191660d09290921b61ffff60d01b16919091179055565b610bfe610bdd60c0830161240f565b6007805461ffff60e01b191660e09290921b61ffff60e01b16919091179055565b610c2f610c0d60e08301612402565b600880546001600160801b0319166001600160801b0392909216919091179055565b610c60610c3f610100830161240f565b6008805461ffff60801b191660809290921b61ffff60801b16919091179055565b610c91610c70610120830161240f565b6008805461ffff60901b191660909290921b61ffff60901b16919091179055565b610cc2610ca1610140830161240f565b6008805461ffff60a01b191660a09290921b61ffff60a01b16919091179055565b0161240f565b6008805461ffff60b01b191660b09290921b61ffff60b01b16919091179055565b3461029a57606036600319011261029a57600435610d0681610289565b6024359060443561600d61304b60f21b015c61029a57602092610d3592600161600d61304b60f21b015d61319a565b5f61600d61304b60f21b015d604051908152f35b3461029a575f36600319011261029a576004546040516001600160a01b039091168152602090f35b3461029a57608036600319011261029a57600435610d8e81610289565b602435906044356001600160401b03811161029a57610db190369060040161053d565b906064356001600160401b03811161029a57610ed1610e2e610e20610e8961044098610e6f610ee098610e206105ef9b610e20610df5610e209b369060040161053d565b604080516001600160a01b039095166020860190815290850198909852999096929182906060820190565b03601f1981018352826107cd565b51902099610e41600b54600c5490611cfd565b90611b4198610e5260208b0161080e565b99808b5261438360208c013960405196879530936020880161257e565b604051928391610e836020840180976125bf565b906125bf565b5190206040516001600160f81b0319602082019081523060601b6bffffffffffffffffffffffff19166021830152603582019590955260558101919091529182906075820190565b5190206001600160a01b031690565b6001600160a01b031690565b3461029a575f36600319011261029a576011546001600160a01b0381163303610f55575f543360018060a01b0382167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a36001600160a01b031990811633175f5516601155005b630614e5c760e21b5f5260045ffd5b3461029a575f36600319011261029a576020601054604051908152f35b3461029a575f36600319011261029a57602060ff600d54166040519015158152f35b3461029a575f36600319011261029a576001546040516001600160a01b039091168152602090f35b3461029a575f36600319011261029a575f546040516001600160a01b039091168152602090f35b608090600319011261029a57600490565b3461029a57608036600319011261029a5761101d36610ff2565b5f546001600160a01b03163303610311578061103a6060926134f5565b61104f6110456125d1565b610aa636846126a0565b61107f813561105d816122b3565b600980546001600160801b0319166001600160801b0392909216919091179055565b6020810135600a556040810135600b550135600c555f516020615ee45f395f51905f525f80a1005b3461029a575f36600319011261029a576020600f54604051908152f35b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b3461029a575f36600319011261029a576104406040516111096040826107cd565b60058152640352e302e360dc1b60208201526040519182916020835260208301906110c4565b3461029a575f36600319011261029a5761600d61304b60f21b015c61029a57600161600d61304b60f21b015d6010545f601055806111a9575b7f41c249580a1c523cc96e0892a3622c677d4cb5de664c55d2ba850edc6508e2676020604051838152a15f61600d61304b60f21b015d604051908152602090f35b6001546111c09082906001600160a01b0316613561565b611168565b3461029a57606036600319011261029a576004356111e281610289565b6024356111ee81610289565b604435906111fb82610289565b5f546001600160a01b03163303610311576001600160a01b03831680158015611286575b8015611275575b6103025761123883836104f0966135ac565b600280546001600160a01b03199081169290921790556004805482166001600160a01b039384161790556006805490911692909116919091179055565b506001600160a01b03831615611226565b506001600160a01b0382161561121f565b604036600319011261029a576004356112af81610289565b6024359061600d61304b60f21b015c61029a57600161600d61304b60f21b015d6001600160a01b038181165f908152600e6020526040902080549093918116156113325760e01c60ff16611323573415611314576104409261076392349133916136f3565b631f2a200560e01b5f5260045ffd5b63e6a0d45f60e01b5f5260045ffd5b638698bf3760e01b5f5260045ffd5b3461029a57602036600319011261029a5761135d600435610289565b61600d61304b60f21b015c61029a57600161600d61304b60f21b015d6001600160a01b03600435165f908152600e6020526040902080546001600160a01b0380821616156113325760ff60e082901c16156118ef5760e81c60ff166118e057805460ff60e81b1916600160e81b1781556001810180545f909155600582015461142d9161140d6113f56001600160801b0384166103b1565b611407608085901c61ffff1684612c94565b90611cfd565b918183116118d6575b6114289060901c61ffff168386613ab7565b611d0f565b60098201549161143c8161314f565b909391926001600160a01b0384163b1561029a57604051630d0e30db60e41b81525f81600481876001600160a01b038a165af1801561181a576118c2575b506001600160a01b0384811660043590911610156118b7576004359184935b6001600160a01b0386811660043590911610156118a7576114ba8189613aff565b905b6040516309f56ab160e11b81526001600160a01b0380871660048301528088166024830152612710604483015283166064820152602081806084810103815f6001600160a01b038e165af191821561181a575f9a6080948989611696968f9661152e9791611878575b50600435613c2d565b9890976001600160a01b03808216600435909116108b1461186757886115778b84839461156983955b836004356001600160a01b0316613e99565b6001600160a01b0316613e99565b61157f6107ee565b6001600160a01b0389168152916001600160a01b038a1660208401526127106040840152620d899f196060840152620d89a08387015260a083015260c082015260e081018b905261010081018b90526001600160a01b038516610120820152426101408201526040519a8b80948193634418b22b60e11b83526004830181516001600160a01b03168152610160810192916101409081906020818101516001600160a01b03169085015260408181015162ffffff169085015260608181015160020b9085015260808181015160020b9085015260a0818101519085015260c0808201519085015260e080820151908501526101008082015190850152610120808201516001600160a01b0316908501520151910152565b03926001600160a01b03165af196871561181a575f97611833575b5081546001600160a01b0391821691166001546005906001600160a01b0316930154946116eb60a087901c61ffff169660b01c61ffff1690565b94833b1561029a576040516355852a8960e01b81526001600160a01b0360048035821690830152602482018c90529384166044820152948316606486015261ffff96871660848601529590941660a484015293841660c48301529290911660e4820152905f908290818381610104810103925af1801561181a5761181f575b506004356001600160a01b03163b1561029a5760405163a69df4b560e01b8152905f826004818382356001600160a01b03165af190811561181a577f6b60d326d3c4023c7cb9b6755fc31af3cfbccdeb07a7a8b4d79e201f732324ee926117f592611806575b506040805194855260208501919091526004356001600160a01b031693918291820190565b0390a35f61600d61304b60f21b015d005b8061078d5f611814936107cd565b5f6117d0565b61218a565b8061078d5f61182d936107cd565b5f61176a565b61185691975060803d608011611860575b61184e81836107cd565b81019061273f565b505050955f6116b1565b503d611844565b886115778b84819461156985611557565b61189a915060203d6020116118a0575b61189281836107cd565b81019061272a565b5f611525565b503d611888565b6118b18882613aff565b906114bc565b839160043593611499565b8061078d5f6118d0936107cd565b5f61147a565b9091508190611416565b6332870f2f60e21b5f5260045ffd5b63d66173a560e01b5f5260045ffd5b3461029a57602036600319011261029a5760043561191b81610289565b61600d61304b60f21b015c61029a57600161600d61304b60f21b015d6001600160a01b039081165f818152600e60205260409020805490921633036119c75760036104409201905f82549255816119b8575b6040518281523391907faa4ecfd5324d73e3b54d038b3ae8ac8f88866d49dc334dc1f02fe36e0f93574890602090a35f61600d61304b60f21b015d6040519081529081906020820190565b6119c28233613561565b61196d565b6393687c0b60e01b5f5260045ffd5b3461029a575f36600319011261029a576006546040516001600160a01b039091168152602090f35b3461029a57604036600319011261029a57602061034b600435611a2081610289565b6024359061276a565b3461029a576102e036600319011261029a57600435611a4781610289565b60243590611a5482610289565b60443591611a6183610289565b60643592611a6e84610289565b60843593611a7b85610289565b6101803660a319011261029a5760803661022319011261029a576108b19460a491610224936102a43595611aae87610470565b6102c43597611abc8961047a565b61282d565b3461029a575f36600319011261029a576011546040516001600160a01b039091168152602090f35b60c036600319011261029a576004356001600160401b03811161029a57611b1490369060040161053d565b6024356001600160401b03811161029a57611b3390369060040161053d565b929091604435926001600160401b03841161029a5761044094611b5d6105ef95369060040161053d565b91606435936084359560a43597611b7389610470565b612b54565b3461029a57602036600319011261029a57600435611b9581610289565b5f546001600160a01b0316903382900361031157601180546001600160a01b0319166001600160a01b03929092169182179055907f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b3461029a57606036600319011261029a576004356024356044356001600160401b03811161029a57611c2590369060040161053d565b61600e61304b60f21b015c6001600160a01b03168015908115611cbf575b50611cb057816040918101031261029a576020813591611c6283610289565b013592611c6e84610289565b5f8113611c95575b50505f8113611c8157005b6108b19133906001600160a01b0316613f52565b611ca99133906001600160a01b0316613f52565b5f80611c76565b637ae3640d60e11b5f5260045ffd5b90503314155f611c43565b80546001600160a01b0319166001600160a01b03909216919091179055565b634e487b7160e01b5f52601160045260245ffd5b91908201809211611d0a57565b611ce9565b91908203918211611d0a57565b81810292918115918404141715611d0a57565b6001600160a01b039081165f908152600e602052604090208054909291811615908115611e24575b508015611e1c575b611e1657611da5611e0491611d9f611d8d61ffff611d86600488015461ffff9060d01c1690565b1683612c94565b611407611d9987612e19565b84612c94565b90611d0f565b6006830154600890611dfc90611dc3906001600160801b03166103b1565b611d9f611dd4600188015483611cfd565b6103db600789015496611df660028b015498611df08a82611d0f565b96611d1c565b92611cfd565b930154611d0f565b9081811115611e11575090565b905090565b50505f90565b508015611d5f565b60e01c60ff1690505f611d57565b91969490939161600d61304b60f21b015c61029a57600161600d61304b60f21b015d611e5c6125d1565b91611e656123cd565b8351909890611e7c906001600160801b03166103b1565b341061217b576040805133602082019081529181019290925290611ea38160608101610e20565b51902093611eba60408a015160608b015190611cfd565b604051611b41808201908282106001600160401b038311176107c857889383928f8c908e611eef9561438388398b309461257e565b03905ff5998a1561181a57600d546001600160a01b038c169b60ff8216918215612173575b82612150575b5050612141578a3b1561029a57604051630cb2654760e31b81525f818d818381611f498a8a3360048501612eac565b03925af19a8b1561181a57611fb987611f838f60049f95611ffc9661212d575b506001600160a01b03165f908152600e6020526040902090565b9d8e611f8f3382611cca565b805467ffffffffffffffff60a01b19164260a01b67ffffffffffffffff60a01b1617815501612ece565b60068c01815181546001600160801b0319166001600160801b03919091161781559060039060609060208101516001850155604081015160028501550151910155565b6006546001600160a01b03161561211e576120ee976120d86103b1978d957f93649bad26bc82d0051a7e0482e2e1ea6e34f341b79098e2e814ed9b599b444f956120e89b8f8b6120ca9161206361205a60025460018060a01b031690565b600a8301611cca565b60045461207c906001600160a01b0316600b8301611cca565b600654612095906001600160a01b0316600c8301611cca565b61209e8c613093565b81516120ba906020906001600160801b031693015161ffff1690565b916001600160801b031690613ab7565b604051968796339b8861310c565b0390a3516001600160801b031690565b34611d0f565b80612109575b50919291505f905061600d61304b60f21b015d565b6121159233908561397d565b505f80806120f4565b632453e80b60e21b5f5260045ffd5b8061078d5f61213b936107cd565b5f611f69565b63280a3b7f60e01b5f5260045ffd5b90915061ffff906121689060081c82165b61ffff1690565b911614155f80611f1a565b5f9250611f14565b63ceaba46f60e01b5f5260045ffd5b6040513d5f823e3d90fd5b90916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016308114908115612291575b5061090a575f546001600160a01b03163303610311576040516352d1902d60e01b8152926020846004816001600160a01b0387165afa5f9481612260575b5061222b57634c9c8ce360e01b5f526001600160a01b03831660045260245ffd5b90915f516020615ec45f395f51905f52840361224c57610491929350614059565b632a87526960e21b5f52600484905260245ffd5b61228391955060203d60201161228a575b61227b81836107cd565b810190613311565b935f61220a565b503d612271565b5f516020615ec45f395f51905f52546001600160a01b0316141590505f6121cc565b6001600160801b0381160361029a57565b3590610491826122b3565b63ffffffff81160361029a57565b3590610491826122cf565b91908261018091031261029a576123c56101606123036107fe565b9361230d816122c4565b855261231b60208201610486565b602086015261232c60408201610486565b604086015261233d606082016122dd565b606086015261234e60808201610486565b608086015261235f60a08201610486565b60a086015261237060c08201610486565b60c086015261238160e082016122c4565b60e08601526123936101008201610486565b6101008601526123a66101208201610486565b6101208601526123b96101408201610486565b61014086015201610486565b610160830152565b604051906123da826107ad565b6009546001600160801b03168252600a546020830152600b546040830152600c546060830152565b3561240c816122b3565b90565b3561240c8161047a565b805461ffff60801b191660809290921b61ffff60801b16919091179055565b805461ffff60901b191660909290921b61ffff60901b16919091179055565b3561240c816122cf565b610cc86101606104919261249861247782612402565b600780546001600160801b0319166001600160801b03909216919091179055565b6124ae6124a76020830161240f565b6007612419565b6124c46124bd6040830161240f565b6007612438565b6124d3610b4960608301612457565b6124e2610b7d6080830161240f565b6124f1610bad60a0830161240f565b612500610bdd60c0830161240f565b61253061250f60e08301612402565b600880546001600160801b0319166001600160801b03909216919091179055565b612547612540610100830161240f565b6008612419565b610c91612557610120830161240f565b6008612438565b908060209392818452848401375f828201840152601f01601f1916010190565b92909361259d6060956125ab949998979960808752608087019161255e565b91848303602086015261255e565b6001600160a01b0390951660408201520152565b805191908290602001825e015f815290565b6125d96107fe565b6007546001600160801b0381168252909190612650906126459061ffff608082901c16602086015261ffff609082901c16604086015263ffffffff60a082901c16606086015261ffff60c082901c16608086015261ffff60d082901c1660a086015260e01c61ffff1690565b61ffff1660c0840152565b6008546001600160801b03811660e084015261ffff608082901c8116610100850152609082901c811661012085015260a082901c81166101408501526104919160b01c1661ffff16610160840152565b919082608091031261029a576040516126b8816107ad565b606080829480356126c8816122b3565b845260208101356020850152604081013560408501520135910152565b60609080356126f3816122b3565b600980546001600160801b0319166001600160801b03929092169190911790556020810135600a556040810135600b550135600c55565b9081602091031261029a575161240c81610289565b919082608091031261029a57815191602081015161275c816122b3565b916060604083015192015190565b6001600160a01b039081165f908152600e60205260409020805490929181161590811561281f575b508015612817575b611e165760068201546127ed906127b9906001600160801b03166103b1565b91611d9f6001850154936103db6127d08683611cfd565b93611df660078901546127e760028b015482611d0f565b94611d1c565b908111611e1657611d9f61ffff612810600461240c95015461ffff9060d01c1690565b1682612c94565b50801561279a565b60e01c60ff1690505f612792565b96949290979593915f516020615f045f395f51905f5254986001600160401b0361286d61286060ff8d60401c1615151590565b9b6001600160401b031690565b1680159081612960575b6001149081612956575b15908161294d575b5061293e576128cc988a6128c360016001600160401b03195f516020615f045f395f51905f525416175f516020615f045f395f51905f5255565b61291a57612968565b6128d257565b5f516020615f045f395f51905f52805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1565b5f516020615f045f395f51905f52805460ff60401b1916600160401b179055612968565b63f92ee8a960e01b5f5260045ffd5b9050155f612889565b303b159150612881565b8b9150612877565b6001600160a01b03811698949794969095909289158015612b43575b8015612b32575b8015612b21575b61030257612ace98612a77612aa396612a55612a9994612a33612a9e98612a11612ab59e6129e28d610aa66129da8e6129ca81613320565b6129d3846134f5565b36906122e8565b9136906126a0565b6001600160a01b038916612af5575f80546001600160a01b0319166001600160a01b0392909216919091179055565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b612461565b6126e5565b60ff8019600d54169115151617600d55565b62ffff00600d549160081b169062ffff00191617600d55565b5f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3565b612b008988876135ac565b5f80546001600160a01b0319166001600160a01b0392909216919091179055565b506001600160a01b03851615612992565b506001600160a01b0381161561298b565b506001600160a01b03831615612984565b95969590949293919261600d61304b60f21b015c61029a57600161600d61304b60f21b015d612b816125d1565b92612b8a6123cd565b8451909990612ba1906001600160801b03166103b1565b341061217b576040805133602082019081529181019290925290612bc88160608101610e20565b51902094612bdf60408b015160608c015190611cfd565b604051611b41808201908282106001600160401b038311176107c857899383928c878f612c139561438388398c309461257e565b03905ff59a8b1561181a57600d546001600160a01b038d169c9060ff8116928315612c6e575b5082612150575050612141578a3b1561029a57604051630cb2654760e31b81525f818d818381611f498a8a3360048501612eac565b92505f612c39565b8115612c80570490565b634e487b7160e01b5f52601260045260245ffd5b612c9e8282613fcf565b918115612cf057816127101115612ce9577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e9193612710910990828211900360fc1b910360041c170290565b6011613fe2565b506127109250500490565b90612d0a600160c01b83613fcf565b9190928315612d825783821115612d75578190600160c01b9009815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b6011600383150218613fe2565b509061240c9250612c76565b91612d998284613fcf565b9290938415612e0c5784831115612dff5790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b6011600384150218613fe2565b50509061240c9250612c76565b600481015463ffffffff8160a01c16918215612e75576001600160401b03905460a01c16420391428311611d0a5780831015612e7557612e6461ffff612e699360901c169384611d1c565b612c76565b8103908111611d0a5790565b5050505f90565b908015612e9a57612e926001915f198401612c76565b019015150290565b634e487b715f5260126020526024601cfd5b6001600160a01b03909116815260406020820181905261240c9391019161255e565b815181546001600160801b0319166001600160801b0390911617815561049191906130779061016090600190612f12612f0c602087015161ffff1690565b82612419565b612f2a612f24604087015161ffff1690565b82612438565b612f5e612f3e606087015163ffffffff1690565b825463ffffffff60a01b191660a09190911b63ffffffff60a01b16178255565b612f8c612f70608087015161ffff1690565b825461ffff60c01b191660c09190911b61ffff60c01b16178255565b612fba612f9e60a087015161ffff1690565b825461ffff60d01b191660d09190911b61ffff60d01b16178255565b612fe8612fcc60c087015161ffff1690565b825461ffff60e01b191660e09190911b61ffff60e01b16178255565b60e0850151910180546001600160801b0319166001600160801b039092169190911781559261302661302061010083015161ffff1690565b85612419565b61303f61303961012083015161ffff1690565b85612438565b61306e61305261014083015161ffff1690565b855461ffff60a01b191660a09190911b61ffff60a01b16178555565b015161ffff1690565b815461ffff60b01b191660b09190911b61ffff60b01b16179055565b600f54600160401b8110156107c85760018101600f55600f548110156130f857600f5f527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b0319166001600160a01b03909216919091179055565b634e487b7160e01b5f52603260045260245ffd5b979695919261314a9461312e61313c936060989660808d5260808d019161255e565b918a830360208c015261255e565b91878303604089015261255e565b930152565b600a810154600b820154600c909201546001600160a01b039182169392821692911690831561317a57565b6002546004546006546001600160a01b0392831696509082169450169150565b6001600160a01b038181165f908152600e6020526040902080549495949092918116156113325760e01c60ff16611323578215611314576001600160a01b0316906131e783303385613ff2565b60068101546131fe906001600160801b03166103b1565b60018201918254926132336132138585611cfd565b611d9f6007850154956103db8a611df660028901996127e78b5482611d0f565b9184831161330257600481019461325d61ffff613256885461ffff9060d01c1690565b1685612c94565b936132688582611d0f565b9a8b106132f3577f01fbb57444511e3de5b26ac09ad6bec45c3f9a1e59dd4a0f2b13a240d18476ce966132ee966132c7956132a76132c1948996611d0f565b90556132b48b8254611d0f565b90555460e01c61ffff1690565b91613ab7565b6132d18733613561565b604080519586526020860188905285015233939081906060820190565b0390a3565b6307dd37f760e41b5f5260045ffd5b6308aed4ef60e31b5f5260045ffd5b9081602091031261029a575190565b6127106133446133356121616040850161240f565b61140761216160a0860161240f565b10156133a05761271061335d612161610100840161240f565b116133a0576127106133746121616020840161240f565b1190811561341e575b8115613403575b81156133e7575b81156133cb575b81156133af575b506133a057565b632b00a33d60e11b5f5260045ffd5b61271091506121616101606133c4920161240f565b115f613399565b90506127106133e0612161610140840161240f565b1190613392565b90506127106133fc612161610120840161240f565b119061338b565b905061271061341761216160c0840161240f565b1190613384565b90506127106134326121616080840161240f565b119061337d565b906134b761348a6134766134566103b1855160018060801b031690565b6103db6134696020870192835190611d1c565b9151604087015190611d0f565b8351611d9f906001600160801b03166103b1565b9261140761ffff6132566101006134ad6103b160e087015160018060801b031690565b94015161ffff1690565b828110156134e6576134ce6060916134e394611d0f565b91016134db828251613aff565b505190613aff565b50565b630d956e1760e21b5f5260045ffd5b6001600160801b0361350682612402565b16158015613555575b8015613549575b61353a576040602082013591013581111561353a576001600160801b031061353a57565b6311c6799960e21b5f5260045ffd5b50606081013515613516565b5060408101351561350f565b5f80809381935af13d156135a7573d6135798161081c565b9061358760405192836107cd565b81525f60203d92013e5b1561359857565b63a0c968e760e01b5f5260045ffd5b613591565b6040516301334da960e11b8152919290916001600160a01b0390911690602081600481855afa90811561181a575f916136d4575b506001600160a01b0316301480159390613675575b508215613614575b505061360557565b63f6e348c960e01b5f5260045ffd5b604051633fc8cef360e01b81529250602090839060049082905afa91821561181a575f92613654575b506001600160a01b03918216911614155f806135fd565b61366e91925060203d6020116118a05761189281836107cd565b905f61363d565b604051637303e91360e01b8152919350602082600481875afa91821561181a575f926136b3575b506001600160a01b0391821691161415915f6135f5565b6136cd91925060203d6020116118a05761189281836107cd565b905f61369c565b6136ed915060203d6020116118a05761189281836107cd565b5f6135e0565b6004820154939594939192909160d01c61ffff1661ffff166137159087612c94565b9561371f84612e19565b6137299082612c94565b908195826137378a84611d0f565b9061374191611d0f565b60068701549094906001600160801b03166001600160801b03169160018801549361376c8585611cfd565b9560078a01549660028b015495613783878a611d0f565b9861378d91611d1c565b906137988a82611cfd565b6137a29083612e7c565b6137ac908a611d0f565b9660088d0154906137bc91611d0f565b915f99838911613909575b50505050505082106132f3576137fd857ef93dbdb72854b6b6fb35433086556f2635fc83c37080c667496fecfa650fb494611cfd565b6001880155613810826002890154611cfd565b6002880155600487015461382c9060e01c61ffff168b89613ab7565b60048701546138439060c01c61ffff168989613ab7565b6138a6613880600289015460088a01541497886138f3575b6001600160a01b0316998a9661387286868a613f52565b806138e3575b50849c611cfd565b60405193849360018060a01b031697846040919493926060820195825260208201520152565b0390a36138b1575050565b600101546040519081527f3a11b9c0ca38b86101cb9e6e1dd2f752c31467c6eaa353f931b801a338406de690602090a2565b6138ed9085613561565b5f613878565b895460ff60e01b1916600160e01b178a5561385b565b91939950918a9f949d508097509994999661392391611d0f565b61392c91612e7c565b9061393691611d0f565b956139448793848094612d8e565b9c8d9261395092612d8e565b998a9261395c91611d0f565b9061396691611d0f565b9061397091611d0f565b93945f80808080806137c7565b909194939261399b61ffff612810600486015461ffff9060d01c1690565b955f946139ac5f6114288a86611d0f565b60068601549093906139c6906001600160801b03166103b1565b926001870154926139d78486611cfd565b946007890154936139f760028b0154956139f18782611d0f565b93611d1c565b96613a22613a17613a11613a0b8c85611cfd565b8b612e7c565b85611d0f565b9660088d0154611d0f565b975f98808811613a62575b505050505082106132f3576137fd857ef93dbdb72854b6b6fb35433086556f2635fc83c37080c667496fecfa650fb494611cfd565b613aa39f99508a9d5061142893949750613a90613aab969b93611428611428946103db85613a99969d611d0f565b9d8e809b612d8e565b9e8f928a5f612d8e565b9c8d94611d0f565b93945f80808080613a2d565b90918215613afa57613acf61ffff6003921684612c94565b9101805490828201809211611d0a57558103908111611d0a57601054908101809111611d0a57601055565b505050565b613b0c90613b1192612cfb565b6140f8565b6401000276a38111801590613b40575b613b31576001600160a01b031690565b63582157bb60e01b5f5260045ffd5b5073fffd8963efd1fc6a506488495d951d5263988d26811015613b21565b908160e091031261029a578051613b7481610289565b9160208201518060020b810361029a57916040810151613b938161047a565b916060820151613ba28161047a565b916080810151613bb18161047a565b9160c060a0830151613bc281610699565b92015161240c81610470565b919082604091031261029a576020825192015190565b6001600160a01b039182168152911515602083015260408201929092529116606082015260a06080820181905261240c929101906110c4565b600160ff1b8114611d0a575f0390565b604051633850c7bd60e01b81529796956001600160a01b0383169591949392909160e08a6004818a5afa998a1561181a575f9a613e72575b506001600160a01b038181169a16808b14613e6457908a6040921192835f14613e5a57613cd986985b6001600160a01b0390811699168914968715613e535786925b61600e61304b60f21b015d84516001600160a01b03918216602082015298166040808a019190915288526060886107cd565b613cf883519788938493630251596160e31b8552873060048701613be4565b03815f8a5af190811561181a575f945f92613e1f575b505f61600e61304b60f21b015d15613e0f57613d2990613c1d565b915b15613df35781613d3e84613d4493611d0f565b96611cfd565b965b604051633850c7bd60e01b815260e081600481895afa90811561181a575f91613dbe575b506001600160a01b031603613daf576040805192835260208301919091527fd81d263c1cd5159bab2e2e9ac2cfd79b7f08afd20b6c2452024791439114cf1791a39190565b6348c6018b60e01b5f5260045ffd5b613de0915060e03d60e011613dec575b613dd881836107cd565b810190613b5e565b5050505050505f613d6a565b503d613dce565b969481613e0384613e0993611d0f565b98611cfd565b94613d46565b92613e1990613c1d565b91613d2b565b909450613e44915060403d604011613e4c575b613e3c81836107cd565b810190613bce565b90935f613d0e565b503d613e32565b8b92613ca7565b613cd98798613c8e565b505050949650505050509190565b613e8c919a5060e03d60e011613dec57613dd881836107cd565b505050505050985f613c65565b60405163095ea7b360e01b5f9081526001600160a01b03841660045260248590529193929160209060448180885af19060015f5114821615613f43575b60405215613ee357505050565b613eed8184614256565b15613f255790613efd91836142bb565b15613f055750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b635274afe760e01b5f9081526001600160a01b038416600452602490fd5b90843b15153d15161690613ed6565b916040519163a9059cbb60e01b5f5260018060a01b031660045260245260205f60448180865af160015f5114811615613fb0575b604091909152155b613f955750565b635274afe760e01b5f526001600160a01b031660045260245ffd5b6001811516613fc6573d15833b15151616613f86565b503d5f823e3d90fd5b905f198183099102908180821091030391565b634e487b715f526020526024601cfd5b6040516323b872dd60e01b5f9081526001600160a01b039384166004529290931660245260449390935260209060648180865af160015f5114811615614043575b6040919091525f60605215613f8e565b6001811516613fc6573d15833b15151616614033565b90813b156140d7575f516020615ec45f395f51905f5280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28051156140bf576134e3916142f6565b5050346140c857565b63b398979f60e01b5f5260045ffd5b50634c9c8ce360e01b5f9081526001600160a01b0391909116600452602490fd5b600181111561240c57806001600160801b821015614219575b6141bf6141b56141ab6141a161419761418d61417c6141c69760046141cb9a600160401b81101561420c575b6401000000008110156141ff575b620100008110156141f2575b6101008110156141e5575b60108110156141d8575b10156141d0575b60030260011c90565b614186818b612c76565b0160011c90565b614186818a612c76565b6141868189612c76565b6141868188612c76565b6141868187612c76565b6141868186612c76565b8093612c76565b821190565b900390565b60011b614173565b60041c9160021b9161416c565b60081c9160041b91614162565b60101c9160081b91614157565b60201c9160101b9161414b565b60401c9160201b9161413d565b50506141cb6141c66141bf6141b56141ab6141a161419761418d61417c6142408a60801c90565b9850600160401b97506141119650505050505050565b60405163095ea7b360e01b5f9081526001600160a01b03909316600452602483905290929160209060448180875af19260015f5114841615614299575b50604052565b600184929415166142b2573b15153d151616915f614293565b833d5f823e3d90fd5b92916040519163095ea7b360e01b5f5260018060a01b031660045260245260205f60448180875af19260015f51148416156142995750604052565b905f8091602081519101845af48080614356575b1561431957505061240c614369565b1561433e57639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b3d15155f0361218a5763d6bda27560e01b5f5260045ffd5b503d15158061430a5750813b151561430a565b604051903d82523d5f602084013e60203d83010160405256fe610180806040523461052857611b41803803809161001d828561052c565b83398101906080818303126105285780516001600160401b038111610528578261004891830161054f565b602082015190926001600160401b0382116105285761006891830161054f565b91604082015160018060a01b03811692838203610528576060015191604094855191610094878461052c565b60018352603160f81b6020840190815281519092906001600160401b03811161042d57600354600181811c9116801561051e575b602082101461040f57601f81116104b0575b50806020601f821160011461044c575f91610441575b508160011b915f199060031b1c1916176003555b8051906001600160401b03821161042d5760045490600182811c92168015610423575b602083101461040f5781601f849311610399575b50602090601f8311600114610333575f92610328575b50508160011b915f199060031b1c1916176004555b61016f816105a4565b6101205261017c83610737565b6101405260208151910120918260e05251902080610100524660a05285519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f84528783015260608201524660808201523060a082015260a081526101e760c08261052c565b5190206080523060c0526101605281156103155760ff60085460a01c16158061030e575b80610306575b806102ff575b6102f057600254908082018092116102dc5760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f936002558484528382528584208181540190558551908152a3516112c5908161087c823960805181610f98015260a05181611055015260c05181610f62015260e05181610fe70152610100518161100d0152610120518161048b015261014051816104b401526101605181818161033f0152818161063c01528181610a3501528181610ece0152610f010152f35b634e487b7160e01b5f52601160045260245ffd5b6336e278fd60e21b5f5260045ffd5b505f610217565b506001610211565b505f61020b565b63ec442f0560e01b5f525f60045260245ffd5b015190505f80610151565b60045f9081528281209350601f198516905b8181106103815750908460019594939210610369575b505050811b01600455610166565b01515f1960f88460031b161c191690555f808061035b565b92936020600181928786015181550195019301610345565b8281111561013b5760045f52909150601f830160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60208510610407575b849392601f0160051c82900391015f5b8281106103f757505061013b565b5f818301558594506001016103e9565b5f91506103d9565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610127565b634e487b7160e01b5f52604160045260245ffd5b90508301515f6100f0565b60035f9081528181209250601f198416905b81811061049857509083600194939210610480575b5050811b01600355610104565b8501515f1960f88460031b161c191690555f80610473565b9192602060018192868a01518155019401920161045e565b818111156100da5760035f52601f820160051c7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b60208410610516575b81601f9101920160051c03905f5b8281106105095750506100da565b5f828201556001016104fb565b5f91506104ed565b90607f16906100c8565b5f80fd5b601f909101601f19168101906001600160401b0382119082101761042d57604052565b81601f82011215610528578051906001600160401b03821161042d5760405192610583601f8401601f19166020018561052c565b8284526020838301011161052857815f9260208093018386015e8301015290565b908151602081105f1461061e575090601f8151116105de5760208151910151602082106105cf571790565b5f198260200360031b1b161790565b604460209160405192839163305a27a960e01b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fd5b6001600160401b03811161042d57600554600181811c9116801561072d575b602082101461040f57601f81116106ee575b50602092601f821160011461068d57928192935f92610682575b50508160011b915f199060031b1c19161760055560ff90565b015190505f80610669565b601f1982169360055f52805f20915f5b8681106106d657508360019596106106be575b505050811b0160055560ff90565b01515f1960f88460031b161c191690555f80806106b0565b9192602060018192868501518155019401920161069d565b8181111561064f5760055f5260205f20601f80840160051c809201920160051c03905f5b82811061072057505061064f565b5f82820155600101610712565b90607f169061063d565b908151602081105f14610762575090601f8151116105de5760208151910151602082106105cf571790565b6001600160401b03811161042d57600654600181811c91168015610871575b602082101461040f57601f8111610832575b50602092601f82116001146107d157928192935f926107c6575b50508160011b915f199060031b1c19161760065560ff90565b015190505f806107ad565b601f1982169360065f52805f20915f5b86811061081a5750836001959610610802575b505050811b0160065560ff90565b01515f1960f88460031b161c191690555f80806107f4565b919260206001819286850151815501940192016107e1565b818111156107935760065f5260205f20601f80840160051c809201920160051c03905f5b828110610864575050610793565b5f82820155600101610856565b90607f169061078156fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610a645750806302669b5214610a2057806302d05d3f146109f857806306fdde0314610953578063095ea7b31461092d57806318160ddd1461091057806323b872dd14610831578063313ce567146108165780633644e515146107f45780633c130d901461012457806365932a38146105ff57806367605787146101245780636a5e2650146105da57806370a08231146105a35780637ecebe001461056b57806384b0196e14610473578063938e3d7b1461012957806395d89b4114610391578063a69df4b51461032d578063a9059cbb146102fc578063d505accf146101b9578063dd62ed3e14610169578063e0df5b6f146101295763e8a3d48514610124575f80fd5b610b07565b346101655760203660031901126101655760043567ffffffffffffffff81116101655761015d610163913690600401610b99565b90610ca2565b005b5f80fd5b3461016557604036600319011261016557610182610adb565b61018a610af1565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b346101655760e0366003190112610165576101d2610adb565b6101da610af1565b604435906064359260843560ff81168103610165578442116102e9576102ae6102b79160018060a01b03841696875f52600760205260405f20908154916001830190556040519060208201927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c984528a604084015260018060a01b038916606084015289608084015260a083015260c082015260c0815261027c60e082610c80565b519020610287610f5f565b906040519161190160f01b83526002830152602282015260c43591604260a4359220611178565b909291926111fb565b6001600160a01b03168481036102d25750610163935061107b565b84906325c0072360e11b5f5260045260245260445ffd5b8463313c898160e11b5f5260045260245ffd5b3461016557604036600319011261016557610322610318610adb565b6024359033610e05565b602060405160018152f35b34610165575f366003190112610165577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610382576008805460ff60a01b1916600160a01b179055005b63236deb5b60e01b5f5260045ffd5b34610165575f366003190112610165576040515f6004546103b181610bc7565b808452906001811690811561044f57506001146103f1575b6103ed836103d981850382610c80565b604051918291602083526020830190610ab7565b0390f35b60045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b808210610435575090915081016020016103d96103c9565b91926001816020925483858801015201910190929161041d565b60ff191660208086019190915291151560051b840190910191506103d990506103c9565b34610165575f3660031901126101655761050f6104af7f00000000000000000000000000000000000000000000000000000000000000006110de565b6104d87f0000000000000000000000000000000000000000000000000000000000000000611141565b602061051d604051926104eb8385610c80565b5f84525f368137604051958695600f60f81b875260e08588015260e0870190610ab7565b908582036040870152610ab7565b4660608501523060808501525f60a085015283810360c08501528180845192838152019301915f5b82811061055457505050500390f35b835185528695509381019392810192600101610545565b34610165576020366003190112610165576001600160a01b0361058c610adb565b165f526007602052602060405f2054604051908152f35b34610165576020366003190112610165576001600160a01b036105c4610adb565b165f525f602052602060405f2054604051908152f35b34610165575f36600319011261016557602060ff60085460a01c166040519015158152f35b3461016557604036600319011261016557610618610adb565b60243567ffffffffffffffff811161016557610638903690600401610b99565b90917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361038257600854906001600160a01b0382166107e6576001600160a01b03166001600160a01b0319919091161760085567ffffffffffffffff81116107d2576106b0600954610bc7565b601f8111610777575b505f601f82116001146107155781925f9261070a575b50508160011b915f199060031b1c1916176009555b7fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad9625f80a1005b0135905082806106cf565b601f1982169260095f5260205f20915f5b85811061075f57508360019510610746575b505050811b016009556106e4565b01355f19600384901b60f8161c19169055828080610738565b90926020600181928686013581550194019101610726565b818111156106b95760095f52601f820160051c5f5160206112705f395f51905f52602084106107ca575b81601f9101920160051c03905f5b8281106107bd5750506106b9565b5f828201556001016107af565b5f91506107a1565b634e487b7160e01b5f52604160045260245ffd5b62dc149f60e41b5f5260045ffd5b34610165575f36600319011261016557602061080e610f5f565b604051908152f35b34610165575f36600319011261016557602060405160128152f35b346101655760603660031901126101655761084a610adb565b610852610af1565b6001600160a01b0382165f818152600160209081526040808320338452909152902054909260443592915f198110610890575b506103229350610e05565b8381106108f55784156108e25733156108cf57610322945f52600160205260405f2060018060a01b0333165f526020528360405f209103905584610885565b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b8390637dc7a0d960e11b5f523360045260245260445260645ffd5b34610165575f366003190112610165576020600254604051908152f35b3461016557604036600319011261016557610322610949610adb565b602435903361107b565b34610165575f366003190112610165576040515f60035461097381610bc7565b808452906001811690811561044f575060011461099a576103ed836103d981850382610c80565b60035f9081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b8082106109de575090915081016020016103d96103c9565b9192600181602092548385880101520191019092916109c6565b34610165575f366003190112610165576008546040516001600160a01b039091168152602090f35b34610165575f366003190112610165576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610165576020366003190112610165576004359063ffffffff60e01b8216809203610165576020916301ffc9a760e01b8114908115610aa6575b5015158152f35b63e8a3d48560e01b14905083610a9f565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361016557565b602435906001600160a01b038216820361016557565b34610165575f366003190112610165576040515f600954610b2781610bc7565b808452906001811690811561044f5750600114610b4e576103ed836103d981850382610c80565b60095f9081525f5160206112705f395f51905f52939250905b808210610b7f575090915081016020016103d96103c9565b919260018160209254838588010152019101909291610b67565b9181601f840112156101655782359167ffffffffffffffff8311610165576020838186019501011161016557565b90600182811c92168015610bf5575b6020831014610be157565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610bd6565b5f9291815491610c0e83610bc7565b8083529260018116908115610c635750600114610c2a57505050565b5f9081526020812093945091925b838310610c49575060209250010190565b600181602092949394548385870101520191019190610c38565b915050602093945060ff929192191683830152151560051b010190565b90601f8019910116810190811067ffffffffffffffff8211176107d257604052565b600854909291906001600160a01b03163303610df65767ffffffffffffffff81116107d257610cd2600954610bc7565b601f8111610d9b575b505f601f8211600114610d38578192935f92610d2d575b50508160011b915f199060031b1c1916176009555b7fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad9625f80a1565b013590505f80610cf2565b601f1982169360095f5260205f20915f5b868110610d835750836001959610610d6a575b505050811b01600955610d07565b01355f19600384901b60f8161c191690555f8080610d5c565b90926020600181928686013581550194019101610d49565b81811115610cdb5760095f52601f820160051c5f5160206112705f395f51905f5260208410610dee575b81601f9101920160051c03905f5b828110610de1575050610cdb565b5f82820155600101610dd3565b5f9150610dc5565b6308f78f9960e31b5f5260045ffd5b6001600160a01b0316908115610f4c576001600160a01b0316918215610f395760ff60085460a01c161580610f31575b80610efe575b80610ecb575b610ebc57815f525f60205260405f2054818110610ea357817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b6336e278fd60e21b5f5260045ffd5b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316831415610e41565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316821415610e3b565b506001610e35565b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480611052575b15610fba577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815261104c60c082610c80565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614610f91565b6001600160a01b03169081156108e2576001600160a01b03169182156108cf5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591835f526001825260405f20855f5282528060405f2055604051908152a3565b60ff81146111245760ff811690601f82116111155760405191611102604084610c80565b6020808452838101919036833783525290565b632cd44ac360e21b5f5260045ffd5b5060405161113e81611137816005610bff565b0382610c80565b90565b60ff81146111655760ff811690601f82116111155760405191611102604084610c80565b5060405161113e81611137816006610bff565b91906fa2a8918ca85bafe22016d0b997e4df60600160ff1b0384116111f0579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156111e5575f516001600160a01b038116156111db57905f905f90565b505f906001905f90565b6040513d5f823e3d90fd5b5050505f9160039190565b600481101561125b578061120d575050565b600181036112245763f645eedf60e01b5f5260045ffd5b6002810361123f575063fce698f760e01b5f5260045260245ffd5b6003146112495750565b6335e2f38360e21b5f5260045260245ffd5b634e487b7160e01b5f52602160045260245ffdfe6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7afa2646970667358221220eb7b697edefabd62959495216215097d50d692990219710ab00c7e1618bb8cf964736f6c63430008230033360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcfe891c6ab12cf73707f8deb6600c12ba382e4cc31eb2b0a2754cad13075ed2d1f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220d55eb83a5fed49f77bf2fec2f3f06ef31e0d6d499831992c81a5e1f6227dc65864736f6c63430008230033f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00
0x60806040526004361015610011575f80fd5b5f3560e01c80630a9d793d146102845780630d7a94f61461027f57806311a15a3b1461027a57806311c2b76c146102755780631daf62d6146102705780631f31905d1461026b5780633fc8cef3146102665780634bf45e8c146102615780634c33aa2e1461025c5780634f1ef2861461025757806352d1902d1461025257806359b6f0dc1461024d5780635e3f2727146102485780636025d89814610243578063634282af1461023e578063690d3c00146102395780636a272462146102345780637303e9131461022f57806374c5bf221461022a57806379ba50971461022557806379ccb4751461022057806387c1ea7f1461021b5780638ce74426146102165780638da5cb5b14610211578063956b79931461020c5780639f181b5e14610207578063ad3cb1cc14610202578063b3dbac77146101fd578063c03dcecd146101f8578063cce7ec13146101f3578063ce5494bb146101ee578063d6ae6e44146101e9578063d7b96d4e146101e4578063d98b2f5c146101df578063e0c6e7c3146101da578063e30c3978146101d5578063e8965ceb146101d0578063f2fde38b146101cb5763fa461e33146101c6575f80fd5b611bef565b611b78565b611ae9565b611ac1565b611a29565b6119fe565b6119d6565b6118fe565b611341565b611297565b6111c5565b61112f565b6110e8565b6110a7565b611003565b610fcb565b610fa3565b610f81565b610f64565b610eec565b610d71565b610d49565b610ce9565b610a52565b6109e6565b6109c2565b6109a6565b610919565b6108b3565b610837565b6106a4565b61063b565b610613565b61056a565b610503565b610493565b610353565b610320565b61029e565b6001600160a01b0381160361029a57565b5f80fd5b3461029a57602036600319011261029a576004356102bb81610289565b5f546001600160a01b03163303610311576001600160a01b0316801561030257600180546001600160a01b0319169190911790555f516020615ee45f395f51905f525f80a1005b63d92e233d60e01b5f5260045ffd5b6330cd747160e01b5f5260045ffd5b3461029a57604036600319011261029a57602061034b60043561034281610289565b60243590611d2f565b604051908152f35b3461029a57602036600319011261029a5760043561037081610289565b6001600160a01b03165f908152600e60205260409020805461044060e082901c60ff169182156104445760068401546103e1906103bd906001600160801b03165b6001600160801b031690565b6103db6103cf60078801548093611d1c565b91600888015490611d0f565b90612e7c565b925b60078501549161040a60086103fd60028901548096611d0f565b9701549160e81c60ff1690565b926040519687968794919260a0949197969360c08701988752602087015260408601526060850152151560808401521515910152565b0390f35b600684015461046a9061045f906001600160801b03166103b1565b600186015490611cfd565b926103e3565b8015150361029a57565b61ffff81160361029a57565b35906104918261047a565b565b3461029a57604036600319011261029a576004356104b081610470565b6024356104bc8161047a565b5f546001600160a01b0316330361031157600d805462ffffff191692151560ff169290921760089190911b62ffff00161790555b5f516020615ee45f395f51905f525f80a1005b3461029a57602036600319011261029a5760043561052081610289565b60018060a01b03165f52600e602052602061034b60405f20612e19565b9181601f8401121561029a578235916001600160401b03831161029a576020838186019501011161029a57565b60a036600319011261029a576004356001600160401b03811161029a5761059590369060040161053d565b906024356001600160401b03811161029a576105b590369060040161053d565b919092604435926001600160401b03841161029a57610440946105df6105ef95369060040161053d565b9290916064359460843596611e32565b6040516001600160a01b0390911681529081906020820190565b5f91031261029a57565b3461029a575f36600319011261029a576002546040516001600160a01b039091168152602090f35b3461029a57602036600319011261029a5760043561065881610289565b60018060a01b03165f52600e602052606061067560405f2061314f565b604080516001600160a01b0394851681529284166020840152921691810191909152f35b60ff81160361029a57565b3461029a5760e036600319011261029a576004356106c181610289565b60243560443560643591608435936106d885610699565b60a43560c4359561600d61304b60f21b015c61029a57600161600d61304b60f21b015d6001600160a01b03831690813b1561029a5760e4610763975f80946104409b60ff97604051988997889663d505accf60e01b88523360048901523060248901528d6044890152606488015216608486015260a485015260c48401525af161077f575b5061319a565b5f61600d61304b60f21b015d6040519081529081906020820190565b8061078d5f610793936107cd565b80610609565b5f61075d565b634e487b7160e01b5f52604160045260245ffd5b608081019081106001600160401b038211176107c857604052565b610799565b90601f801991011681019081106001600160401b038211176107c857604052565b60405190610491610160836107cd565b60405190610491610180836107cd565b9061049160405192836107cd565b6001600160401b0381116107c857601f01601f191660200190565b604036600319011261029a5760043561084f81610289565b602435906001600160401b03821161029a573660238301121561029a5781600401359061087b8261081c565b9161088960405193846107cd565b808352366024828601011161029a576020815f9260246108b197018387013784010152612195565b005b3461029a575f36600319011261029a577f00000000000000000000000077faab5c351c67eba6938705aba721c9e28d523d6001600160a01b0316300361090a5760206040515f516020615ec45f395f51905f528152f35b63703e46dd60e11b5f5260045ffd5b3461029a57602036600319011261029a5760043561093681610289565b6001600160a01b039081165f908152600e60209081526040918290208054600182015460028301546003909301548551968316875260ff60e084901c811615159588019590955260e89290921c9093161515938501939093526060840191909152608083015260a082015260c090f35b3461029a575f36600319011261029a5760206040516127108152f35b3461029a575f36600319011261029a57602061ffff600d5460081c16604051908152f35b3461029a57602036600319011261029a57600435600f5481101561029a57600f5f527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac80201546040516001600160a01b039091168152602090f35b61018090600319011261029a57600490565b3461029a5761018036600319011261029a57610a6d36610a40565b5f546001600160a01b0316330361031157610cc861016082610a916104f094613320565b610aac610a9e36836122e8565b610aa66123cd565b90613439565b610ada610ab882612402565b600780546001600160801b0319166001600160801b0392909216919091179055565b610b0a610ae96020830161240f565b6007805461ffff60801b191660809290921b61ffff60801b16919091179055565b610b3a610b196040830161240f565b6007805461ffff60901b191660909290921b61ffff60901b16919091179055565b610b6e610b4960608301612457565b6007805463ffffffff60a01b191660a09290921b63ffffffff60a01b16919091179055565b610b9e610b7d6080830161240f565b6007805461ffff60c01b191660c09290921b61ffff60c01b16919091179055565b610bce610bad60a0830161240f565b6007805461ffff60d01b191660d09290921b61ffff60d01b16919091179055565b610bfe610bdd60c0830161240f565b6007805461ffff60e01b191660e09290921b61ffff60e01b16919091179055565b610c2f610c0d60e08301612402565b600880546001600160801b0319166001600160801b0392909216919091179055565b610c60610c3f610100830161240f565b6008805461ffff60801b191660809290921b61ffff60801b16919091179055565b610c91610c70610120830161240f565b6008805461ffff60901b191660909290921b61ffff60901b16919091179055565b610cc2610ca1610140830161240f565b6008805461ffff60a01b191660a09290921b61ffff60a01b16919091179055565b0161240f565b6008805461ffff60b01b191660b09290921b61ffff60b01b16919091179055565b3461029a57606036600319011261029a57600435610d0681610289565b6024359060443561600d61304b60f21b015c61029a57602092610d3592600161600d61304b60f21b015d61319a565b5f61600d61304b60f21b015d604051908152f35b3461029a575f36600319011261029a576004546040516001600160a01b039091168152602090f35b3461029a57608036600319011261029a57600435610d8e81610289565b602435906044356001600160401b03811161029a57610db190369060040161053d565b906064356001600160401b03811161029a57610ed1610e2e610e20610e8961044098610e6f610ee098610e206105ef9b610e20610df5610e209b369060040161053d565b604080516001600160a01b039095166020860190815290850198909852999096929182906060820190565b03601f1981018352826107cd565b51902099610e41600b54600c5490611cfd565b90611b4198610e5260208b0161080e565b99808b5261438360208c013960405196879530936020880161257e565b604051928391610e836020840180976125bf565b906125bf565b5190206040516001600160f81b0319602082019081523060601b6bffffffffffffffffffffffff19166021830152603582019590955260558101919091529182906075820190565b5190206001600160a01b031690565b6001600160a01b031690565b3461029a575f36600319011261029a576011546001600160a01b0381163303610f55575f543360018060a01b0382167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a36001600160a01b031990811633175f5516601155005b630614e5c760e21b5f5260045ffd5b3461029a575f36600319011261029a576020601054604051908152f35b3461029a575f36600319011261029a57602060ff600d54166040519015158152f35b3461029a575f36600319011261029a576001546040516001600160a01b039091168152602090f35b3461029a575f36600319011261029a575f546040516001600160a01b039091168152602090f35b608090600319011261029a57600490565b3461029a57608036600319011261029a5761101d36610ff2565b5f546001600160a01b03163303610311578061103a6060926134f5565b61104f6110456125d1565b610aa636846126a0565b61107f813561105d816122b3565b600980546001600160801b0319166001600160801b0392909216919091179055565b6020810135600a556040810135600b550135600c555f516020615ee45f395f51905f525f80a1005b3461029a575f36600319011261029a576020600f54604051908152f35b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b3461029a575f36600319011261029a576104406040516111096040826107cd565b60058152640352e302e360dc1b60208201526040519182916020835260208301906110c4565b3461029a575f36600319011261029a5761600d61304b60f21b015c61029a57600161600d61304b60f21b015d6010545f601055806111a9575b7f41c249580a1c523cc96e0892a3622c677d4cb5de664c55d2ba850edc6508e2676020604051838152a15f61600d61304b60f21b015d604051908152602090f35b6001546111c09082906001600160a01b0316613561565b611168565b3461029a57606036600319011261029a576004356111e281610289565b6024356111ee81610289565b604435906111fb82610289565b5f546001600160a01b03163303610311576001600160a01b03831680158015611286575b8015611275575b6103025761123883836104f0966135ac565b600280546001600160a01b03199081169290921790556004805482166001600160a01b039384161790556006805490911692909116919091179055565b506001600160a01b03831615611226565b506001600160a01b0382161561121f565b604036600319011261029a576004356112af81610289565b6024359061600d61304b60f21b015c61029a57600161600d61304b60f21b015d6001600160a01b038181165f908152600e6020526040902080549093918116156113325760e01c60ff16611323573415611314576104409261076392349133916136f3565b631f2a200560e01b5f5260045ffd5b63e6a0d45f60e01b5f5260045ffd5b638698bf3760e01b5f5260045ffd5b3461029a57602036600319011261029a5761135d600435610289565b61600d61304b60f21b015c61029a57600161600d61304b60f21b015d6001600160a01b03600435165f908152600e6020526040902080546001600160a01b0380821616156113325760ff60e082901c16156118ef5760e81c60ff166118e057805460ff60e81b1916600160e81b1781556001810180545f909155600582015461142d9161140d6113f56001600160801b0384166103b1565b611407608085901c61ffff1684612c94565b90611cfd565b918183116118d6575b6114289060901c61ffff168386613ab7565b611d0f565b60098201549161143c8161314f565b909391926001600160a01b0384163b1561029a57604051630d0e30db60e41b81525f81600481876001600160a01b038a165af1801561181a576118c2575b506001600160a01b0384811660043590911610156118b7576004359184935b6001600160a01b0386811660043590911610156118a7576114ba8189613aff565b905b6040516309f56ab160e11b81526001600160a01b0380871660048301528088166024830152612710604483015283166064820152602081806084810103815f6001600160a01b038e165af191821561181a575f9a6080948989611696968f9661152e9791611878575b50600435613c2d565b9890976001600160a01b03808216600435909116108b1461186757886115778b84839461156983955b836004356001600160a01b0316613e99565b6001600160a01b0316613e99565b61157f6107ee565b6001600160a01b0389168152916001600160a01b038a1660208401526127106040840152620d899f196060840152620d89a08387015260a083015260c082015260e081018b905261010081018b90526001600160a01b038516610120820152426101408201526040519a8b80948193634418b22b60e11b83526004830181516001600160a01b03168152610160810192916101409081906020818101516001600160a01b03169085015260408181015162ffffff169085015260608181015160020b9085015260808181015160020b9085015260a0818101519085015260c0808201519085015260e080820151908501526101008082015190850152610120808201516001600160a01b0316908501520151910152565b03926001600160a01b03165af196871561181a575f97611833575b5081546001600160a01b0391821691166001546005906001600160a01b0316930154946116eb60a087901c61ffff169660b01c61ffff1690565b94833b1561029a576040516355852a8960e01b81526001600160a01b0360048035821690830152602482018c90529384166044820152948316606486015261ffff96871660848601529590941660a484015293841660c48301529290911660e4820152905f908290818381610104810103925af1801561181a5761181f575b506004356001600160a01b03163b1561029a5760405163a69df4b560e01b8152905f826004818382356001600160a01b03165af190811561181a577f6b60d326d3c4023c7cb9b6755fc31af3cfbccdeb07a7a8b4d79e201f732324ee926117f592611806575b506040805194855260208501919091526004356001600160a01b031693918291820190565b0390a35f61600d61304b60f21b015d005b8061078d5f611814936107cd565b5f6117d0565b61218a565b8061078d5f61182d936107cd565b5f61176a565b61185691975060803d608011611860575b61184e81836107cd565b81019061273f565b505050955f6116b1565b503d611844565b886115778b84819461156985611557565b61189a915060203d6020116118a0575b61189281836107cd565b81019061272a565b5f611525565b503d611888565b6118b18882613aff565b906114bc565b839160043593611499565b8061078d5f6118d0936107cd565b5f61147a565b9091508190611416565b6332870f2f60e21b5f5260045ffd5b63d66173a560e01b5f5260045ffd5b3461029a57602036600319011261029a5760043561191b81610289565b61600d61304b60f21b015c61029a57600161600d61304b60f21b015d6001600160a01b039081165f818152600e60205260409020805490921633036119c75760036104409201905f82549255816119b8575b6040518281523391907faa4ecfd5324d73e3b54d038b3ae8ac8f88866d49dc334dc1f02fe36e0f93574890602090a35f61600d61304b60f21b015d6040519081529081906020820190565b6119c28233613561565b61196d565b6393687c0b60e01b5f5260045ffd5b3461029a575f36600319011261029a576006546040516001600160a01b039091168152602090f35b3461029a57604036600319011261029a57602061034b600435611a2081610289565b6024359061276a565b3461029a576102e036600319011261029a57600435611a4781610289565b60243590611a5482610289565b60443591611a6183610289565b60643592611a6e84610289565b60843593611a7b85610289565b6101803660a319011261029a5760803661022319011261029a576108b19460a491610224936102a43595611aae87610470565b6102c43597611abc8961047a565b61282d565b3461029a575f36600319011261029a576011546040516001600160a01b039091168152602090f35b60c036600319011261029a576004356001600160401b03811161029a57611b1490369060040161053d565b6024356001600160401b03811161029a57611b3390369060040161053d565b929091604435926001600160401b03841161029a5761044094611b5d6105ef95369060040161053d565b91606435936084359560a43597611b7389610470565b612b54565b3461029a57602036600319011261029a57600435611b9581610289565b5f546001600160a01b0316903382900361031157601180546001600160a01b0319166001600160a01b03929092169182179055907f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b3461029a57606036600319011261029a576004356024356044356001600160401b03811161029a57611c2590369060040161053d565b61600e61304b60f21b015c6001600160a01b03168015908115611cbf575b50611cb057816040918101031261029a576020813591611c6283610289565b013592611c6e84610289565b5f8113611c95575b50505f8113611c8157005b6108b19133906001600160a01b0316613f52565b611ca99133906001600160a01b0316613f52565b5f80611c76565b637ae3640d60e11b5f5260045ffd5b90503314155f611c43565b80546001600160a01b0319166001600160a01b03909216919091179055565b634e487b7160e01b5f52601160045260245ffd5b91908201809211611d0a57565b611ce9565b91908203918211611d0a57565b81810292918115918404141715611d0a57565b6001600160a01b039081165f908152600e602052604090208054909291811615908115611e24575b508015611e1c575b611e1657611da5611e0491611d9f611d8d61ffff611d86600488015461ffff9060d01c1690565b1683612c94565b611407611d9987612e19565b84612c94565b90611d0f565b6006830154600890611dfc90611dc3906001600160801b03166103b1565b611d9f611dd4600188015483611cfd565b6103db600789015496611df660028b015498611df08a82611d0f565b96611d1c565b92611cfd565b930154611d0f565b9081811115611e11575090565b905090565b50505f90565b508015611d5f565b60e01c60ff1690505f611d57565b91969490939161600d61304b60f21b015c61029a57600161600d61304b60f21b015d611e5c6125d1565b91611e656123cd565b8351909890611e7c906001600160801b03166103b1565b341061217b576040805133602082019081529181019290925290611ea38160608101610e20565b51902093611eba60408a015160608b015190611cfd565b604051611b41808201908282106001600160401b038311176107c857889383928f8c908e611eef9561438388398b309461257e565b03905ff5998a1561181a57600d546001600160a01b038c169b60ff8216918215612173575b82612150575b5050612141578a3b1561029a57604051630cb2654760e31b81525f818d818381611f498a8a3360048501612eac565b03925af19a8b1561181a57611fb987611f838f60049f95611ffc9661212d575b506001600160a01b03165f908152600e6020526040902090565b9d8e611f8f3382611cca565b805467ffffffffffffffff60a01b19164260a01b67ffffffffffffffff60a01b1617815501612ece565b60068c01815181546001600160801b0319166001600160801b03919091161781559060039060609060208101516001850155604081015160028501550151910155565b6006546001600160a01b03161561211e576120ee976120d86103b1978d957f93649bad26bc82d0051a7e0482e2e1ea6e34f341b79098e2e814ed9b599b444f956120e89b8f8b6120ca9161206361205a60025460018060a01b031690565b600a8301611cca565b60045461207c906001600160a01b0316600b8301611cca565b600654612095906001600160a01b0316600c8301611cca565b61209e8c613093565b81516120ba906020906001600160801b031693015161ffff1690565b916001600160801b031690613ab7565b604051968796339b8861310c565b0390a3516001600160801b031690565b34611d0f565b80612109575b50919291505f905061600d61304b60f21b015d565b6121159233908561397d565b505f80806120f4565b632453e80b60e21b5f5260045ffd5b8061078d5f61213b936107cd565b5f611f69565b63280a3b7f60e01b5f5260045ffd5b90915061ffff906121689060081c82165b61ffff1690565b911614155f80611f1a565b5f9250611f14565b63ceaba46f60e01b5f5260045ffd5b6040513d5f823e3d90fd5b90916001600160a01b037f00000000000000000000000077faab5c351c67eba6938705aba721c9e28d523d16308114908115612291575b5061090a575f546001600160a01b03163303610311576040516352d1902d60e01b8152926020846004816001600160a01b0387165afa5f9481612260575b5061222b57634c9c8ce360e01b5f526001600160a01b03831660045260245ffd5b90915f516020615ec45f395f51905f52840361224c57610491929350614059565b632a87526960e21b5f52600484905260245ffd5b61228391955060203d60201161228a575b61227b81836107cd565b810190613311565b935f61220a565b503d612271565b5f516020615ec45f395f51905f52546001600160a01b0316141590505f6121cc565b6001600160801b0381160361029a57565b3590610491826122b3565b63ffffffff81160361029a57565b3590610491826122cf565b91908261018091031261029a576123c56101606123036107fe565b9361230d816122c4565b855261231b60208201610486565b602086015261232c60408201610486565b604086015261233d606082016122dd565b606086015261234e60808201610486565b608086015261235f60a08201610486565b60a086015261237060c08201610486565b60c086015261238160e082016122c4565b60e08601526123936101008201610486565b6101008601526123a66101208201610486565b6101208601526123b96101408201610486565b61014086015201610486565b610160830152565b604051906123da826107ad565b6009546001600160801b03168252600a546020830152600b546040830152600c546060830152565b3561240c816122b3565b90565b3561240c8161047a565b805461ffff60801b191660809290921b61ffff60801b16919091179055565b805461ffff60901b191660909290921b61ffff60901b16919091179055565b3561240c816122cf565b610cc86101606104919261249861247782612402565b600780546001600160801b0319166001600160801b03909216919091179055565b6124ae6124a76020830161240f565b6007612419565b6124c46124bd6040830161240f565b6007612438565b6124d3610b4960608301612457565b6124e2610b7d6080830161240f565b6124f1610bad60a0830161240f565b612500610bdd60c0830161240f565b61253061250f60e08301612402565b600880546001600160801b0319166001600160801b03909216919091179055565b612547612540610100830161240f565b6008612419565b610c91612557610120830161240f565b6008612438565b908060209392818452848401375f828201840152601f01601f1916010190565b92909361259d6060956125ab949998979960808752608087019161255e565b91848303602086015261255e565b6001600160a01b0390951660408201520152565b805191908290602001825e015f815290565b6125d96107fe565b6007546001600160801b0381168252909190612650906126459061ffff608082901c16602086015261ffff609082901c16604086015263ffffffff60a082901c16606086015261ffff60c082901c16608086015261ffff60d082901c1660a086015260e01c61ffff1690565b61ffff1660c0840152565b6008546001600160801b03811660e084015261ffff608082901c8116610100850152609082901c811661012085015260a082901c81166101408501526104919160b01c1661ffff16610160840152565b919082608091031261029a576040516126b8816107ad565b606080829480356126c8816122b3565b845260208101356020850152604081013560408501520135910152565b60609080356126f3816122b3565b600980546001600160801b0319166001600160801b03929092169190911790556020810135600a556040810135600b550135600c55565b9081602091031261029a575161240c81610289565b919082608091031261029a57815191602081015161275c816122b3565b916060604083015192015190565b6001600160a01b039081165f908152600e60205260409020805490929181161590811561281f575b508015612817575b611e165760068201546127ed906127b9906001600160801b03166103b1565b91611d9f6001850154936103db6127d08683611cfd565b93611df660078901546127e760028b015482611d0f565b94611d1c565b908111611e1657611d9f61ffff612810600461240c95015461ffff9060d01c1690565b1682612c94565b50801561279a565b60e01c60ff1690505f612792565b96949290979593915f516020615f045f395f51905f5254986001600160401b0361286d61286060ff8d60401c1615151590565b9b6001600160401b031690565b1680159081612960575b6001149081612956575b15908161294d575b5061293e576128cc988a6128c360016001600160401b03195f516020615f045f395f51905f525416175f516020615f045f395f51905f5255565b61291a57612968565b6128d257565b5f516020615f045f395f51905f52805460ff60401b19169055604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1565b5f516020615f045f395f51905f52805460ff60401b1916600160401b179055612968565b63f92ee8a960e01b5f5260045ffd5b9050155f612889565b303b159150612881565b8b9150612877565b6001600160a01b03811698949794969095909289158015612b43575b8015612b32575b8015612b21575b61030257612ace98612a77612aa396612a55612a9994612a33612a9e98612a11612ab59e6129e28d610aa66129da8e6129ca81613320565b6129d3846134f5565b36906122e8565b9136906126a0565b6001600160a01b038916612af5575f80546001600160a01b0319166001600160a01b0392909216919091179055565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b612461565b6126e5565b60ff8019600d54169115151617600d55565b62ffff00600d549160081b169062ffff00191617600d55565b5f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3565b612b008988876135ac565b5f80546001600160a01b0319166001600160a01b0392909216919091179055565b506001600160a01b03851615612992565b506001600160a01b0381161561298b565b506001600160a01b03831615612984565b95969590949293919261600d61304b60f21b015c61029a57600161600d61304b60f21b015d612b816125d1565b92612b8a6123cd565b8451909990612ba1906001600160801b03166103b1565b341061217b576040805133602082019081529181019290925290612bc88160608101610e20565b51902094612bdf60408b015160608c015190611cfd565b604051611b41808201908282106001600160401b038311176107c857899383928c878f612c139561438388398c309461257e565b03905ff59a8b1561181a57600d546001600160a01b038d169c9060ff8116928315612c6e575b5082612150575050612141578a3b1561029a57604051630cb2654760e31b81525f818d818381611f498a8a3360048501612eac565b92505f612c39565b8115612c80570490565b634e487b7160e01b5f52601260045260245ffd5b612c9e8282613fcf565b918115612cf057816127101115612ce9577fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e9193612710910990828211900360fc1b910360041c170290565b6011613fe2565b506127109250500490565b90612d0a600160c01b83613fcf565b9190928315612d825783821115612d75578190600160c01b9009815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b6011600383150218613fe2565b509061240c9250612c76565b91612d998284613fcf565b9290938415612e0c5784831115612dff5790829109815f0382168092046002816003021880820260020302808202600203028082026002030280820260020302808202600203028091026002030293600183805f03040190848311900302920304170290565b6011600384150218613fe2565b50509061240c9250612c76565b600481015463ffffffff8160a01c16918215612e75576001600160401b03905460a01c16420391428311611d0a5780831015612e7557612e6461ffff612e699360901c169384611d1c565b612c76565b8103908111611d0a5790565b5050505f90565b908015612e9a57612e926001915f198401612c76565b019015150290565b634e487b715f5260126020526024601cfd5b6001600160a01b03909116815260406020820181905261240c9391019161255e565b815181546001600160801b0319166001600160801b0390911617815561049191906130779061016090600190612f12612f0c602087015161ffff1690565b82612419565b612f2a612f24604087015161ffff1690565b82612438565b612f5e612f3e606087015163ffffffff1690565b825463ffffffff60a01b191660a09190911b63ffffffff60a01b16178255565b612f8c612f70608087015161ffff1690565b825461ffff60c01b191660c09190911b61ffff60c01b16178255565b612fba612f9e60a087015161ffff1690565b825461ffff60d01b191660d09190911b61ffff60d01b16178255565b612fe8612fcc60c087015161ffff1690565b825461ffff60e01b191660e09190911b61ffff60e01b16178255565b60e0850151910180546001600160801b0319166001600160801b039092169190911781559261302661302061010083015161ffff1690565b85612419565b61303f61303961012083015161ffff1690565b85612438565b61306e61305261014083015161ffff1690565b855461ffff60a01b191660a09190911b61ffff60a01b16178555565b015161ffff1690565b815461ffff60b01b191660b09190911b61ffff60b01b16179055565b600f54600160401b8110156107c85760018101600f55600f548110156130f857600f5f527f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac8020180546001600160a01b0319166001600160a01b03909216919091179055565b634e487b7160e01b5f52603260045260245ffd5b979695919261314a9461312e61313c936060989660808d5260808d019161255e565b918a830360208c015261255e565b91878303604089015261255e565b930152565b600a810154600b820154600c909201546001600160a01b039182169392821692911690831561317a57565b6002546004546006546001600160a01b0392831696509082169450169150565b6001600160a01b038181165f908152600e6020526040902080549495949092918116156113325760e01c60ff16611323578215611314576001600160a01b0316906131e783303385613ff2565b60068101546131fe906001600160801b03166103b1565b60018201918254926132336132138585611cfd565b611d9f6007850154956103db8a611df660028901996127e78b5482611d0f565b9184831161330257600481019461325d61ffff613256885461ffff9060d01c1690565b1685612c94565b936132688582611d0f565b9a8b106132f3577f01fbb57444511e3de5b26ac09ad6bec45c3f9a1e59dd4a0f2b13a240d18476ce966132ee966132c7956132a76132c1948996611d0f565b90556132b48b8254611d0f565b90555460e01c61ffff1690565b91613ab7565b6132d18733613561565b604080519586526020860188905285015233939081906060820190565b0390a3565b6307dd37f760e41b5f5260045ffd5b6308aed4ef60e31b5f5260045ffd5b9081602091031261029a575190565b6127106133446133356121616040850161240f565b61140761216160a0860161240f565b10156133a05761271061335d612161610100840161240f565b116133a0576127106133746121616020840161240f565b1190811561341e575b8115613403575b81156133e7575b81156133cb575b81156133af575b506133a057565b632b00a33d60e11b5f5260045ffd5b61271091506121616101606133c4920161240f565b115f613399565b90506127106133e0612161610140840161240f565b1190613392565b90506127106133fc612161610120840161240f565b119061338b565b905061271061341761216160c0840161240f565b1190613384565b90506127106134326121616080840161240f565b119061337d565b906134b761348a6134766134566103b1855160018060801b031690565b6103db6134696020870192835190611d1c565b9151604087015190611d0f565b8351611d9f906001600160801b03166103b1565b9261140761ffff6132566101006134ad6103b160e087015160018060801b031690565b94015161ffff1690565b828110156134e6576134ce6060916134e394611d0f565b91016134db828251613aff565b505190613aff565b50565b630d956e1760e21b5f5260045ffd5b6001600160801b0361350682612402565b16158015613555575b8015613549575b61353a576040602082013591013581111561353a576001600160801b031061353a57565b6311c6799960e21b5f5260045ffd5b50606081013515613516565b5060408101351561350f565b5f80809381935af13d156135a7573d6135798161081c565b9061358760405192836107cd565b81525f60203d92013e5b1561359857565b63a0c968e760e01b5f5260045ffd5b613591565b6040516301334da960e11b8152919290916001600160a01b0390911690602081600481855afa90811561181a575f916136d4575b506001600160a01b0316301480159390613675575b508215613614575b505061360557565b63f6e348c960e01b5f5260045ffd5b604051633fc8cef360e01b81529250602090839060049082905afa91821561181a575f92613654575b506001600160a01b03918216911614155f806135fd565b61366e91925060203d6020116118a05761189281836107cd565b905f61363d565b604051637303e91360e01b8152919350602082600481875afa91821561181a575f926136b3575b506001600160a01b0391821691161415915f6135f5565b6136cd91925060203d6020116118a05761189281836107cd565b905f61369c565b6136ed915060203d6020116118a05761189281836107cd565b5f6135e0565b6004820154939594939192909160d01c61ffff1661ffff166137159087612c94565b9561371f84612e19565b6137299082612c94565b908195826137378a84611d0f565b9061374191611d0f565b60068701549094906001600160801b03166001600160801b03169160018801549361376c8585611cfd565b9560078a01549660028b015495613783878a611d0f565b9861378d91611d1c565b906137988a82611cfd565b6137a29083612e7c565b6137ac908a611d0f565b9660088d0154906137bc91611d0f565b915f99838911613909575b50505050505082106132f3576137fd857ef93dbdb72854b6b6fb35433086556f2635fc83c37080c667496fecfa650fb494611cfd565b6001880155613810826002890154611cfd565b6002880155600487015461382c9060e01c61ffff168b89613ab7565b60048701546138439060c01c61ffff168989613ab7565b6138a6613880600289015460088a01541497886138f3575b6001600160a01b0316998a9661387286868a613f52565b806138e3575b50849c611cfd565b60405193849360018060a01b031697846040919493926060820195825260208201520152565b0390a36138b1575050565b600101546040519081527f3a11b9c0ca38b86101cb9e6e1dd2f752c31467c6eaa353f931b801a338406de690602090a2565b6138ed9085613561565b5f613878565b895460ff60e01b1916600160e01b178a5561385b565b91939950918a9f949d508097509994999661392391611d0f565b61392c91612e7c565b9061393691611d0f565b956139448793848094612d8e565b9c8d9261395092612d8e565b998a9261395c91611d0f565b9061396691611d0f565b9061397091611d0f565b93945f80808080806137c7565b909194939261399b61ffff612810600486015461ffff9060d01c1690565b955f946139ac5f6114288a86611d0f565b60068601549093906139c6906001600160801b03166103b1565b926001870154926139d78486611cfd565b946007890154936139f760028b0154956139f18782611d0f565b93611d1c565b96613a22613a17613a11613a0b8c85611cfd565b8b612e7c565b85611d0f565b9660088d0154611d0f565b975f98808811613a62575b505050505082106132f3576137fd857ef93dbdb72854b6b6fb35433086556f2635fc83c37080c667496fecfa650fb494611cfd565b613aa39f99508a9d5061142893949750613a90613aab969b93611428611428946103db85613a99969d611d0f565b9d8e809b612d8e565b9e8f928a5f612d8e565b9c8d94611d0f565b93945f80808080613a2d565b90918215613afa57613acf61ffff6003921684612c94565b9101805490828201809211611d0a57558103908111611d0a57601054908101809111611d0a57601055565b505050565b613b0c90613b1192612cfb565b6140f8565b6401000276a38111801590613b40575b613b31576001600160a01b031690565b63582157bb60e01b5f5260045ffd5b5073fffd8963efd1fc6a506488495d951d5263988d26811015613b21565b908160e091031261029a578051613b7481610289565b9160208201518060020b810361029a57916040810151613b938161047a565b916060820151613ba28161047a565b916080810151613bb18161047a565b9160c060a0830151613bc281610699565b92015161240c81610470565b919082604091031261029a576020825192015190565b6001600160a01b039182168152911515602083015260408201929092529116606082015260a06080820181905261240c929101906110c4565b600160ff1b8114611d0a575f0390565b604051633850c7bd60e01b81529796956001600160a01b0383169591949392909160e08a6004818a5afa998a1561181a575f9a613e72575b506001600160a01b038181169a16808b14613e6457908a6040921192835f14613e5a57613cd986985b6001600160a01b0390811699168914968715613e535786925b61600e61304b60f21b015d84516001600160a01b03918216602082015298166040808a019190915288526060886107cd565b613cf883519788938493630251596160e31b8552873060048701613be4565b03815f8a5af190811561181a575f945f92613e1f575b505f61600e61304b60f21b015d15613e0f57613d2990613c1d565b915b15613df35781613d3e84613d4493611d0f565b96611cfd565b965b604051633850c7bd60e01b815260e081600481895afa90811561181a575f91613dbe575b506001600160a01b031603613daf576040805192835260208301919091527fd81d263c1cd5159bab2e2e9ac2cfd79b7f08afd20b6c2452024791439114cf1791a39190565b6348c6018b60e01b5f5260045ffd5b613de0915060e03d60e011613dec575b613dd881836107cd565b810190613b5e565b5050505050505f613d6a565b503d613dce565b969481613e0384613e0993611d0f565b98611cfd565b94613d46565b92613e1990613c1d565b91613d2b565b909450613e44915060403d604011613e4c575b613e3c81836107cd565b810190613bce565b90935f613d0e565b503d613e32565b8b92613ca7565b613cd98798613c8e565b505050949650505050509190565b613e8c919a5060e03d60e011613dec57613dd881836107cd565b505050505050985f613c65565b60405163095ea7b360e01b5f9081526001600160a01b03841660045260248590529193929160209060448180885af19060015f5114821615613f43575b60405215613ee357505050565b613eed8184614256565b15613f255790613efd91836142bb565b15613f055750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b635274afe760e01b5f9081526001600160a01b038416600452602490fd5b90843b15153d15161690613ed6565b916040519163a9059cbb60e01b5f5260018060a01b031660045260245260205f60448180865af160015f5114811615613fb0575b604091909152155b613f955750565b635274afe760e01b5f526001600160a01b031660045260245ffd5b6001811516613fc6573d15833b15151616613f86565b503d5f823e3d90fd5b905f198183099102908180821091030391565b634e487b715f526020526024601cfd5b6040516323b872dd60e01b5f9081526001600160a01b039384166004529290931660245260449390935260209060648180865af160015f5114811615614043575b6040919091525f60605215613f8e565b6001811516613fc6573d15833b15151616614033565b90813b156140d7575f516020615ec45f395f51905f5280546001600160a01b0319166001600160a01b0384169081179091557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28051156140bf576134e3916142f6565b5050346140c857565b63b398979f60e01b5f5260045ffd5b50634c9c8ce360e01b5f9081526001600160a01b0391909116600452602490fd5b600181111561240c57806001600160801b821015614219575b6141bf6141b56141ab6141a161419761418d61417c6141c69760046141cb9a600160401b81101561420c575b6401000000008110156141ff575b620100008110156141f2575b6101008110156141e5575b60108110156141d8575b10156141d0575b60030260011c90565b614186818b612c76565b0160011c90565b614186818a612c76565b6141868189612c76565b6141868188612c76565b6141868187612c76565b6141868186612c76565b8093612c76565b821190565b900390565b60011b614173565b60041c9160021b9161416c565b60081c9160041b91614162565b60101c9160081b91614157565b60201c9160101b9161414b565b60401c9160201b9161413d565b50506141cb6141c66141bf6141b56141ab6141a161419761418d61417c6142408a60801c90565b9850600160401b97506141119650505050505050565b60405163095ea7b360e01b5f9081526001600160a01b03909316600452602483905290929160209060448180875af19260015f5114841615614299575b50604052565b600184929415166142b2573b15153d151616915f614293565b833d5f823e3d90fd5b92916040519163095ea7b360e01b5f5260018060a01b031660045260245260205f60448180875af19260015f51148416156142995750604052565b905f8091602081519101845af48080614356575b1561431957505061240c614369565b1561433e57639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b3d15155f0361218a5763d6bda27560e01b5f5260045ffd5b503d15158061430a5750813b151561430a565b604051903d82523d5f602084013e60203d83010160405256fe610180806040523461052857611b41803803809161001d828561052c565b83398101906080818303126105285780516001600160401b038111610528578261004891830161054f565b602082015190926001600160401b0382116105285761006891830161054f565b91604082015160018060a01b03811692838203610528576060015191604094855191610094878461052c565b60018352603160f81b6020840190815281519092906001600160401b03811161042d57600354600181811c9116801561051e575b602082101461040f57601f81116104b0575b50806020601f821160011461044c575f91610441575b508160011b915f199060031b1c1916176003555b8051906001600160401b03821161042d5760045490600182811c92168015610423575b602083101461040f5781601f849311610399575b50602090601f8311600114610333575f92610328575b50508160011b915f199060031b1c1916176004555b61016f816105a4565b6101205261017c83610737565b6101405260208151910120918260e05251902080610100524660a05285519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f84528783015260608201524660808201523060a082015260a081526101e760c08261052c565b5190206080523060c0526101605281156103155760ff60085460a01c16158061030e575b80610306575b806102ff575b6102f057600254908082018092116102dc5760207fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef915f936002558484528382528584208181540190558551908152a3516112c5908161087c823960805181610f98015260a05181611055015260c05181610f62015260e05181610fe70152610100518161100d0152610120518161048b015261014051816104b401526101605181818161033f0152818161063c01528181610a3501528181610ece0152610f010152f35b634e487b7160e01b5f52601160045260245ffd5b6336e278fd60e21b5f5260045ffd5b505f610217565b506001610211565b505f61020b565b63ec442f0560e01b5f525f60045260245ffd5b015190505f80610151565b60045f9081528281209350601f198516905b8181106103815750908460019594939210610369575b505050811b01600455610166565b01515f1960f88460031b161c191690555f808061035b565b92936020600181928786015181550195019301610345565b8281111561013b5760045f52909150601f830160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b60208510610407575b849392601f0160051c82900391015f5b8281106103f757505061013b565b5f818301558594506001016103e9565b5f91506103d9565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610127565b634e487b7160e01b5f52604160045260245ffd5b90508301515f6100f0565b60035f9081528181209250601f198416905b81811061049857509083600194939210610480575b5050811b01600355610104565b8501515f1960f88460031b161c191690555f80610473565b9192602060018192868a01518155019401920161045e565b818111156100da5760035f52601f820160051c7fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b60208410610516575b81601f9101920160051c03905f5b8281106105095750506100da565b5f828201556001016104fb565b5f91506104ed565b90607f16906100c8565b5f80fd5b601f909101601f19168101906001600160401b0382119082101761042d57604052565b81601f82011215610528578051906001600160401b03821161042d5760405192610583601f8401601f19166020018561052c565b8284526020838301011161052857815f9260208093018386015e8301015290565b908151602081105f1461061e575090601f8151116105de5760208151910151602082106105cf571790565b5f198260200360031b1b161790565b604460209160405192839163305a27a960e01b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fd5b6001600160401b03811161042d57600554600181811c9116801561072d575b602082101461040f57601f81116106ee575b50602092601f821160011461068d57928192935f92610682575b50508160011b915f199060031b1c19161760055560ff90565b015190505f80610669565b601f1982169360055f52805f20915f5b8681106106d657508360019596106106be575b505050811b0160055560ff90565b01515f1960f88460031b161c191690555f80806106b0565b9192602060018192868501518155019401920161069d565b8181111561064f5760055f5260205f20601f80840160051c809201920160051c03905f5b82811061072057505061064f565b5f82820155600101610712565b90607f169061063d565b908151602081105f14610762575090601f8151116105de5760208151910151602082106105cf571790565b6001600160401b03811161042d57600654600181811c91168015610871575b602082101461040f57601f8111610832575b50602092601f82116001146107d157928192935f926107c6575b50508160011b915f199060031b1c19161760065560ff90565b015190505f806107ad565b601f1982169360065f52805f20915f5b86811061081a5750836001959610610802575b505050811b0160065560ff90565b01515f1960f88460031b161c191690555f80806107f4565b919260206001819286850151815501940192016107e1565b818111156107935760065f5260205f20601f80840160051c809201920160051c03905f5b828110610864575050610793565b5f82820155600101610856565b90607f169061078156fe6080806040526004361015610012575f80fd5b5f3560e01c90816301ffc9a714610a645750806302669b5214610a2057806302d05d3f146109f857806306fdde0314610953578063095ea7b31461092d57806318160ddd1461091057806323b872dd14610831578063313ce567146108165780633644e515146107f45780633c130d901461012457806365932a38146105ff57806367605787146101245780636a5e2650146105da57806370a08231146105a35780637ecebe001461056b57806384b0196e14610473578063938e3d7b1461012957806395d89b4114610391578063a69df4b51461032d578063a9059cbb146102fc578063d505accf146101b9578063dd62ed3e14610169578063e0df5b6f146101295763e8a3d48514610124575f80fd5b610b07565b346101655760203660031901126101655760043567ffffffffffffffff81116101655761015d610163913690600401610b99565b90610ca2565b005b5f80fd5b3461016557604036600319011261016557610182610adb565b61018a610af1565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b346101655760e0366003190112610165576101d2610adb565b6101da610af1565b604435906064359260843560ff81168103610165578442116102e9576102ae6102b79160018060a01b03841696875f52600760205260405f20908154916001830190556040519060208201927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c984528a604084015260018060a01b038916606084015289608084015260a083015260c082015260c0815261027c60e082610c80565b519020610287610f5f565b906040519161190160f01b83526002830152602282015260c43591604260a4359220611178565b909291926111fb565b6001600160a01b03168481036102d25750610163935061107b565b84906325c0072360e11b5f5260045260245260445ffd5b8463313c898160e11b5f5260045260245ffd5b3461016557604036600319011261016557610322610318610adb565b6024359033610e05565b602060405160018152f35b34610165575f366003190112610165577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610382576008805460ff60a01b1916600160a01b179055005b63236deb5b60e01b5f5260045ffd5b34610165575f366003190112610165576040515f6004546103b181610bc7565b808452906001811690811561044f57506001146103f1575b6103ed836103d981850382610c80565b604051918291602083526020830190610ab7565b0390f35b60045f9081527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b808210610435575090915081016020016103d96103c9565b91926001816020925483858801015201910190929161041d565b60ff191660208086019190915291151560051b840190910191506103d990506103c9565b34610165575f3660031901126101655761050f6104af7f00000000000000000000000000000000000000000000000000000000000000006110de565b6104d87f0000000000000000000000000000000000000000000000000000000000000000611141565b602061051d604051926104eb8385610c80565b5f84525f368137604051958695600f60f81b875260e08588015260e0870190610ab7565b908582036040870152610ab7565b4660608501523060808501525f60a085015283810360c08501528180845192838152019301915f5b82811061055457505050500390f35b835185528695509381019392810192600101610545565b34610165576020366003190112610165576001600160a01b0361058c610adb565b165f526007602052602060405f2054604051908152f35b34610165576020366003190112610165576001600160a01b036105c4610adb565b165f525f602052602060405f2054604051908152f35b34610165575f36600319011261016557602060ff60085460a01c166040519015158152f35b3461016557604036600319011261016557610618610adb565b60243567ffffffffffffffff811161016557610638903690600401610b99565b90917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316330361038257600854906001600160a01b0382166107e6576001600160a01b03166001600160a01b0319919091161760085567ffffffffffffffff81116107d2576106b0600954610bc7565b601f8111610777575b505f601f82116001146107155781925f9261070a575b50508160011b915f199060031b1c1916176009555b7fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad9625f80a1005b0135905082806106cf565b601f1982169260095f5260205f20915f5b85811061075f57508360019510610746575b505050811b016009556106e4565b01355f19600384901b60f8161c19169055828080610738565b90926020600181928686013581550194019101610726565b818111156106b95760095f52601f820160051c5f5160206112705f395f51905f52602084106107ca575b81601f9101920160051c03905f5b8281106107bd5750506106b9565b5f828201556001016107af565b5f91506107a1565b634e487b7160e01b5f52604160045260245ffd5b62dc149f60e41b5f5260045ffd5b34610165575f36600319011261016557602061080e610f5f565b604051908152f35b34610165575f36600319011261016557602060405160128152f35b346101655760603660031901126101655761084a610adb565b610852610af1565b6001600160a01b0382165f818152600160209081526040808320338452909152902054909260443592915f198110610890575b506103229350610e05565b8381106108f55784156108e25733156108cf57610322945f52600160205260405f2060018060a01b0333165f526020528360405f209103905584610885565b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b8390637dc7a0d960e11b5f523360045260245260445260645ffd5b34610165575f366003190112610165576020600254604051908152f35b3461016557604036600319011261016557610322610949610adb565b602435903361107b565b34610165575f366003190112610165576040515f60035461097381610bc7565b808452906001811690811561044f575060011461099a576103ed836103d981850382610c80565b60035f9081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b939250905b8082106109de575090915081016020016103d96103c9565b9192600181602092548385880101520191019092916109c6565b34610165575f366003190112610165576008546040516001600160a01b039091168152602090f35b34610165575f366003190112610165576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610165576020366003190112610165576004359063ffffffff60e01b8216809203610165576020916301ffc9a760e01b8114908115610aa6575b5015158152f35b63e8a3d48560e01b14905083610a9f565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361016557565b602435906001600160a01b038216820361016557565b34610165575f366003190112610165576040515f600954610b2781610bc7565b808452906001811690811561044f5750600114610b4e576103ed836103d981850382610c80565b60095f9081525f5160206112705f395f51905f52939250905b808210610b7f575090915081016020016103d96103c9565b919260018160209254838588010152019101909291610b67565b9181601f840112156101655782359167ffffffffffffffff8311610165576020838186019501011161016557565b90600182811c92168015610bf5575b6020831014610be157565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610bd6565b5f9291815491610c0e83610bc7565b8083529260018116908115610c635750600114610c2a57505050565b5f9081526020812093945091925b838310610c49575060209250010190565b600181602092949394548385870101520191019190610c38565b915050602093945060ff929192191683830152151560051b010190565b90601f8019910116810190811067ffffffffffffffff8211176107d257604052565b600854909291906001600160a01b03163303610df65767ffffffffffffffff81116107d257610cd2600954610bc7565b601f8111610d9b575b505f601f8211600114610d38578192935f92610d2d575b50508160011b915f199060031b1c1916176009555b7fa5d4097edda6d87cb9329af83fb3712ef77eeb13738ffe43cc35a4ce305ad9625f80a1565b013590505f80610cf2565b601f1982169360095f5260205f20915f5b868110610d835750836001959610610d6a575b505050811b01600955610d07565b01355f19600384901b60f8161c191690555f8080610d5c565b90926020600181928686013581550194019101610d49565b81811115610cdb5760095f52601f820160051c5f5160206112705f395f51905f5260208410610dee575b81601f9101920160051c03905f5b828110610de1575050610cdb565b5f82820155600101610dd3565b5f9150610dc5565b6308f78f9960e31b5f5260045ffd5b6001600160a01b0316908115610f4c576001600160a01b0316918215610f395760ff60085460a01c161580610f31575b80610efe575b80610ecb575b610ebc57815f525f60205260405f2054818110610ea357817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b6336e278fd60e21b5f5260045ffd5b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316831415610e41565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316821415610e3b565b506001610e35565b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480611052575b15610fba577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a0815261104c60c082610c80565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614610f91565b6001600160a01b03169081156108e2576001600160a01b03169182156108cf5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591835f526001825260405f20855f5282528060405f2055604051908152a3565b60ff81146111245760ff811690601f82116111155760405191611102604084610c80565b6020808452838101919036833783525290565b632cd44ac360e21b5f5260045ffd5b5060405161113e81611137816005610bff565b0382610c80565b90565b60ff81146111655760ff811690601f82116111155760405191611102604084610c80565b5060405161113e81611137816006610bff565b91906fa2a8918ca85bafe22016d0b997e4df60600160ff1b0384116111f0579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa156111e5575f516001600160a01b038116156111db57905f905f90565b505f906001905f90565b6040513d5f823e3d90fd5b5050505f9160039190565b600481101561125b578061120d575050565b600181036112245763f645eedf60e01b5f5260045ffd5b6002810361123f575063fce698f760e01b5f5260045260245ffd5b6003146112495750565b6335e2f38360e21b5f5260045260245ffd5b634e487b7160e01b5f52602160045260245ffdfe6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7afa2646970667358221220eb7b697edefabd62959495216215097d50d692990219710ab00c7e1618bb8cf964736f6c63430008230033360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcfe891c6ab12cf73707f8deb6600c12ba382e4cc31eb2b0a2754cad13075ed2d1f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220d55eb83a5fed49f77bf2fec2f3f06ef31e0d6d499831992c81a5e1f6227dc65864736f6c63430008230033
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 16,114,439 | 26 days agoWed, 22 Jul 2026 03:48:49 UTC | 0xbd073d…0bb71c | DELEGATECALL | createToken | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.1505 ETH |
| 16,113,494 | 26 days agoWed, 22 Jul 2026 03:47:15 UTC | 0x80c634…17d78e | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.01 ETH |
| 16,113,466 | 26 days agoWed, 22 Jul 2026 03:47:12 UTC | 0x5ad4f8…1847b2 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.03333 ETH |
| 16,113,466 | 26 days agoWed, 22 Jul 2026 03:47:12 UTC | 0xe40637…3a618f | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.03333 ETH |
| 16,113,466 | 26 days agoWed, 22 Jul 2026 03:47:12 UTC | 0x49bb63…182012 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.03333 ETH |
| 16,113,451 | 26 days agoWed, 22 Jul 2026 03:47:11 UTC | 0x91686e…3a191d | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.01 ETH |
| 16,113,440 | 26 days agoWed, 22 Jul 2026 03:47:10 UTC | 0xf27f6d…dbb31f | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.001 ETH |
| 16,113,157 | 26 days agoWed, 22 Jul 2026 03:46:41 UTC | 0x65293f…c0b4ae | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.005 ETH |
| 16,113,011 | 26 days agoWed, 22 Jul 2026 03:46:26 UTC | 0xefa446…059d89 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.05 ETH |
| 16,112,946 | 26 days agoWed, 22 Jul 2026 03:46:20 UTC | 0x5c081f…13c9ba | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.0025 ETH |
| 16,112,946 | 26 days agoWed, 22 Jul 2026 03:46:20 UTC | 0x85a713…f0b356 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.0025 ETH |
| 16,112,894 | 26 days agoWed, 22 Jul 2026 03:46:15 UTC | 0x0ae939…6222fa | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.2 ETH |
| 16,112,579 | 26 days agoWed, 22 Jul 2026 03:45:43 UTC | 0x9ebc4d…fee694 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.01666 ETH |
| 16,112,579 | 26 days agoWed, 22 Jul 2026 03:45:43 UTC | 0xdad759…bdbe00 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.01666 ETH |
| 16,112,579 | 26 days agoWed, 22 Jul 2026 03:45:43 UTC | 0xd60242…e95a57 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.01666 ETH |
| 16,112,570 | 26 days agoWed, 22 Jul 2026 03:45:42 UTC | 0x067e86…e5aa66 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.002 ETH |
| 16,112,568 | 26 days agoWed, 22 Jul 2026 03:45:42 UTC | 0x051d83…76580f | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.005 ETH |
| 16,112,549 | 26 days agoWed, 22 Jul 2026 03:45:40 UTC | 0xde7496…e81f3a | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.04 ETH |
| 16,112,500 | 26 days agoWed, 22 Jul 2026 03:45:35 UTC | 0x2ba6b9…dc979f | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.003 ETH |
| 16,112,498 | 26 days agoWed, 22 Jul 2026 03:45:35 UTC | 0xabd8ce…714cce | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.0025 ETH |
| 16,112,469 | 26 days agoWed, 22 Jul 2026 03:45:32 UTC | 0x299d9c…ee7637 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.014 ETH |
| 16,112,422 | 26 days agoWed, 22 Jul 2026 03:45:27 UTC | 0x80adda…8eedfa | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.025 ETH |
| 16,112,422 | 26 days agoWed, 22 Jul 2026 03:45:27 UTC | 0x0a5a65…0f7d76 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.025 ETH |
| 16,112,422 | 26 days agoWed, 22 Jul 2026 03:45:27 UTC | 0x5fc6f0…f338b5 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.025 ETH |
| 16,112,422 | 26 days agoWed, 22 Jul 2026 03:45:27 UTC | 0x33a1dd…4e3a91 | DELEGATECALL | buy | 0xb7fa…cb00 | IN | 0x77fa…523d | 0.025 ETH |