false
true
0

Contract Address Details

0xFFFFfd64EFFb1f789BFDbB94DB682bc764E4FFFF

Token
Moon (MOON)
Creator
0x8cd0f5–b38522 at 0x8939d6–460829
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
26612485
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
Moon




Optimization enabled
true
Compiler version
v0.8.24+commit.e11b9ed9




Optimization runs
6000
EVM Version
paris




Verified at
2026-05-13T20:01:09.388686Z

Constructor Arguments

000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000029ea7545def87022badc76323f373ea1e707c523000000000000000000000000000000000000000000000000000000000000001d0000000000000000000000000000674bc7700311b62845e2f5cdd4aff9990000000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff000000000000000000000000133ba2cdf20af0878bf0fcee6878caa5f506045b000000000000000000000000000000000000000000000000000000003b9aca00

Arg [0] (uint256) : 1000000000
Arg [1] (address) : 0x29ea7545def87022badc76323f373ea1e707c523
Arg [2] (uint24) : 29
Arg [3] (address) : 0x0000674bc7700311b62845e2f5cdd4aff9990000
Arg [4] (address) : 0xffff33ad6ab86cfe721ddfe97eac10958240ffff
Arg [5] (address) : 0x133ba2cdf20af0878bf0fcee6878caa5f506045b
Arg [6] (uint256) : 1000000000

              

contracts/Moon.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/* 
 ┌────────────────────────────────────────────────────────────────────────┐
 │                                                                        │
 │                 ███    ███  ██████   ██████  ███    ██                 │
 │                 ████  ████ ██    ██ ██    ██ ████   ██                 │
 │                 ██ ████ ██ ██    ██ ██    ██ ██ ██  ██                 │
 │                 ██  ██  ██ ██    ██ ██    ██ ██  ██ ██                 │
 │                 ██      ██  ██████   ██████  ██   ████                 │
 │                                                                        │
 │                                                                        │
 │  MOON is the heart of a fully decentralized discovery system. It       │
 │  converts swap activity into reflections for SUN holders while         │
 │  benefiting every project that pairs with it.                          │       
 │                                                                        │
 │  How it works                                                          │
 │   • All swaps through official PulseX V2 pairs are taxed 3%.           │                             
 │   • MOON uses the tax to buy back the paired token and distributes it  │
 │     to SUN holders automatically.                                      │
 │   • Wallet transfers, liquidity mints/burns as well as swaps on other  │
 │     DEXs are untaxed.                                                  │
 │                                                                        │
 │  Add your token                                                        │                                                     
 │   • Create a V2 liquidity pair with your token and MOON on PulseX:     │                                                                                  
 │        → Add your token first.                                         │
 │        → Add MOON second. (PulseX UI: MOON on the bottom)              │
 │   • This lets you add/remove liquidity tax free and plugs your         │
 │     token into the reflection system automatically.                    │
 │                                                                        │
 │  Why pair with MOON?                                                   │
 │   • Organic exposure: Natural arbitrage connects your token directly   │
 │     with SUN holders, building awareness without paid promotion.       │
 │   • Constant buy pressure: whether users buy or sell through the pair, │
 │     the tax is always used to buy your token.                          │
 │   • Enhanced LP rewards: a built-in “pair bonus” leaves part of        │
 │     swap-back yield in the pool, boosting LP take on top of V2 fees.   │
 │                                                                        │
 └────────────────────────────────────────────────────────────────────────┘
*/

/*────────────────────────────  INTERFACES  ─────────────────────────────*/

/// @dev Minimal ERC-20 subset used by this contract.
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/// @dev Uniswap V2 Pair subset used by the contract’s swap-backs.
interface IUniswapV2Pair {
    function swap(
        uint amount0Out,  
        uint amount1Out,
        address to,
        bytes calldata data
    ) external;
}

/// @notice Vault payout used in _emitRay.
interface IVault {
    function releaseToMember(address ray, uint256 amount, address member) external;
}

/// @notice All other external calls use precomputed selectors

/*──────────────────────── FLOAT‑96 CODEC (88+8) ────────────────────────*/

/// @title Uint256 <-> Float96 (88-bit mantissa + 8-bit exponent)
/// @notice Compact, lossy encoding for non-negative uint256 values.
/// @dev Layout: packed[95:88]=exponent, packed[87:0]=mantissa.
///      Decodes as (mantissa << exponent). Rounding = nearest, ties-to-even.
library Uint256Float96 {
    uint256 private constant MANTISSA_BITS = 88;
    uint256 private constant EXPONENT_BITS = 8; // reserved for clarity
    uint256 private constant MANTISSA_MASK = (uint256(1) << MANTISSA_BITS) - 1;
    uint8   private constant MAX_EXPONENT  = 168; // 256 - 88

    error BadPackedExponent(uint8 e);

    /// @notice Encode a uint256 into a uint96 float-like value.
    /// @dev Exact for values < 2^88 (exponent=0). Larger values are rounded
    ///      to nearest, ties-to-even; may saturate if exponent would overflow.
    function encode(uint256 x) internal pure returns (uint96 packed) {
        if (x == 0) return 0;

        // Find msb(x). After this block: bitLen = floor(log2(x)) + 1.
        uint256 msb;
        unchecked {
            uint256 y = x;
            if (y >= 1 << 128) { y >>= 128; msb += 128; }
            if (y >= 1 <<  64) { y >>=  64; msb +=  64; }
            if (y >= 1 <<  32) { y >>=  32; msb +=  32; }
            if (y >= 1 <<  16) { y >>=  16; msb +=  16; }
            if (y >= 1 <<   8) { y >>=   8; msb +=   8; }
            if (y >= 1 <<   4) { y >>=   4; msb +=   4; }
            if (y >= 1 <<   2) { y >>=   2; msb +=   2; }
            if (y >= 1 <<   1) {           msb +=   1; }
        }
        uint256 bitLen = msb + 1;

        // Fits entirely in mantissa -> exponent=0, exact store.
        if (bitLen <= MANTISSA_BITS) {
            return uint96(x);
        }

        // Normalize into 88-bit mantissa and an exponent in [1..168].
        uint256 shift = bitLen - MANTISSA_BITS;
        uint256 mant  = x >> shift;

        // Round to nearest, ties-to-even.
        {
            uint256 remMask = (uint256(1) << shift) - 1;
            uint256 rem     = x & remMask;
            uint256 half    = uint256(1) << (shift - 1);
            bool roundUp    = (rem > half) || (rem == half && (mant & 1) == 1);

            if (roundUp) {
                unchecked { mant += 1; }
                // If rounding overflowed mantissa to 2^88, renormalize.
                if (mant == (uint256(1) << MANTISSA_BITS)) {
                    mant >>= 1;
                    shift += 1;
                }
            }
        }

        // Saturate if exponent would exceed representable range.
        if (shift > MAX_EXPONENT) {
            shift = MAX_EXPONENT;
            mant  = MANTISSA_MASK;
        }

        // Pack: [ exponent | mantissa ].
        return (uint96(uint8(shift)) << uint96(MANTISSA_BITS)) | uint96(mant & MANTISSA_MASK);
    }

    /// @notice Decode a packed uint96 back into a uint256.
    /// @dev Reverts if exponent field is malformed (> MAX_EXPONENT).
    function decode(uint96 packed) internal pure returns (uint256 x) {
        uint8 exponent = uint8(packed >> MANTISSA_BITS);
        if (exponent > MAX_EXPONENT) revert BadPackedExponent(exponent);

        uint256 mantissa = uint256(packed) & MANTISSA_MASK;
        return mantissa << exponent;
    }
}

/*────────────────────────────────  MOON  ───────────────────────────────*/

/// @title Moon (MOON)
/// @notice ERC‑20 token with integrated pair‑aware taxation and SUN reflections.
contract Moon is IERC20 {

    /*//////////////////////////////////////////////////////////////////////
                                  METADATA                                
    //////////////////////////////////////////////////////////////////////*/

    /// @notice Token name.
    string  public constant name     = "Moon";
    /// @notice Token symbol.
    string  public constant symbol   = "MOON";
    /// @notice Token decimals (fixed at 18).
    uint8   public constant decimals = 18;

    /*//////////////////////////////////////////////////////////////////////
                                    EVENTS                                 
    //////////////////////////////////////////////////////////////////////*/

    /// @dev Fired once when a new ray (paired token) is discovered & cached.
    event RayInitialized(address indexed ray);

    /*//////////////////////////////////////////////////////////////////////
                                  IMMUTABLES                               
    //////////////////////////////////////////////////////////////////////*/

    /// @notice Total SUN supply credited at deploy (1e18‑scaled).
    uint256 public immutable totalSunSupply;

    /// @notice Verified Uniswap‑style V2 factory used for pair recognition.
    address public immutable factory;

    /// @notice SUN ERC‑20 contract linked for distributions.
    address public immutable sun;

    /// @notice Vault that custodies Rays.
    address public immutable vault;

    /// @notice Uniswap‑style fee in basis points (e.g., 30 for 0.30%).
    uint24  public immutable feeBps;

    /// @notice Multiplier used in x*y=k fee math: (FEE_DENOMINATOR - feeBps).
    /// @dev Example: 9_970 for a 0.30% fee.
    uint24  public immutable feeMul;

    /*//////////////////////////////////////////////////////////////////////
                                   CONSTANTS                                
    //////////////////////////////////////////////////////////////////////*/

    /// @dev Basis points denominator for AMM fee math (10_000 = 100%).
    uint24 public constant FEE_DENOMINATOR     = 10_000;

    /// @notice Swap tax rate (3%).
    uint256 public constant SWAP_TAX           = 3e16;

    /// @notice Percentage of swap-back left in the pair as an LP bonus (25%).
    uint256 public constant PAIR_BONUS         = 25e16;

    /// @notice Appreciation tax applied to positive value deltas (20%).
    uint256 public constant APPRECIATION_TAX   = 20e16;

    /// @notice Gas stipend for the radiation loop.
    uint256 public constant RADIATE_GAS_LIMIT  = 220_000;

    /// @notice Gas stipend for swapBack.
    uint256 public constant SWAPBACK_CALL_GAS  = 350_000;

    /// @notice Minimum pending MOON before a swap-back is attempted (1 MOON).
    uint256 public constant MIN_SWAP_BACK      = 1e18;

    /// @notice Minimum value emitted per payout (1e-9 MOON).
    uint256 public constant MIN_EMIT           = 1e9;

    /// @notice Minimum SUN tokens for automatic payout (1 SUN)
    /// Members below this threshold can still call collect()
    uint256 public constant MIN_SUN_RADIATE    = 1e18;

    /// @notice Maximum distinct tokens to attempt in a single payout iteration.
    uint256 public constant MAX_PAYOUT_TOKENS  = 6;

    /// @notice Index scaling factor (1e32) — “index decimals”.
    uint256 public constant INDEX_DECIMALS     = 1e32;

    /// @notice Conventional burn sink address (irretrievable).
    /// @dev Tokens sent here are considered permanently destroyed.
    address public constant DEAD = 0x000000000000000000000000000000000000dEaD;

    /*//////////////////////////////////////////////////////////////////////
                                ERC-20 STORAGE                             
    //////////////////////////////////////////////////////////////////////*/

    /// @notice Current total supply of MOON tokens in existence.
    /// @dev This value is initialized at deployment and monotonically decreases 
    ///      as tokens are burned. There is no mechanism to increase supply.
    uint256 public override totalSupply;

    /// @dev MOON balances.
    mapping(address => uint256) internal balances;

    /// @dev ERC‑20 allowances: owner => (spender => amount).
    mapping(address => mapping(address => uint256)) internal allowances;

    /*//////////////////////////////////////////////////////////////////////
                           CLASSIFICATION BOOKKEEPING                         
    //////////////////////////////////////////////////////////////////////*/
    
    /*
     * moonClass:
     *   0 = unknown (not yet probed)
     *   1 = regular holder or non‑verified contract
     *   2 = verified V2 pair that contains MOON (taxed)
     */
    mapping(address => uint8) internal moonClass;

    /*//////////////////////////////////////////////////////////////////////
                               SUN MEMBER STATE                            
    //////////////////////////////////////////////////////////////////////*/

    /// @dev Member accounting snapshot (first four fields are persisted).
    struct Member {
        // persisted fields
        uint128 pastIndex;   // index snapshot (1e32‑scaled)
        uint112 uncollected; // uncollected value (MOON‑value terms)
        uint8   class;       // 0 unknown | 1 eligible | 2 ineligible
        uint8   status;      // 0 not active | 1 queued for removal | 2 active

        // transient helpers (NEVER written to storage) 
        address self;        // member address in memory
        uint256 balance;     // SUN balance (queried lazily)
    }

    /// @dev Member records (only the first four fields are read/written).
    mapping(address => Member) internal members;

    /*//////////////////////////////////////////////////////////////////////
                               RAY TOKEN STATE                        
    //////////////////////////////////////////////////////////////////////*/

    /// @dev Ray = per‑token accounting for a reflection asset paired with MOON.
    struct Ray {
        // slot 0
        address pair;             // verified V2 pair that contains MOON & this ray

        // slot 1 (tightly packed to 256 bits)
        uint112 reserve;          // current Vault balance credited as “value bearing”
        uint112 pending;          // pending MOON earmarked for swap‑back
        uint8   swapStatus;       // 0 not listed | 2 in swapQueue
        uint8   brightStatus;     // 0 not listed | 1 pending removal | 2 in brightRays
        bool    thisZero;         // true if MOON is token0 in the pair

        // slot 2 (tightly packed to 256 bits)
        uint96  quote96;          // MOON per token, 1e38‑scaled (compressed)
        uint96  candidateQuote96; // intra‑block max quote (compressed)
        uint64  updateBlock;      // last quote update block

        // transient helpers (NEVER written to storage)
        address self;             // this ray address (for convenience)
        uint256 ra;               // pair’s ray reserve (pre‑event)
        uint256 rm;               // pair’s MOON reserve (pre‑event)
        uint256 quote;            // decoded committed quote (1e38‑scaled)
        uint256 candidateQuote;   // decoded candidate quote (1e38‑scaled)
        uint256 cursor;           // place in brightRays list during emitRay
    }

    /// @dev Per‑token accounting. Public getter exposes persisted fields.
    mapping(address => Ray) internal rays;

    /*//////////////////////////////////////////////////////////////////////
                                  PAIR STATE                        
    //////////////////////////////////////////////////////////////////////*/

     /// @dev Per-pair bookkeeping.
    struct Pair {
        address ray;       // Ray associated with that pair
        bool    swapLock;  // prevents swaps during untaxed mints/burns
    }

    /// @notice Registered pairs containing MOON, keyed by pair address.
    mapping(address => Pair) public pairs;

    /*//////////////////////////////////////////////////////////////////////
                          GLOBAL AGGREGATES (PACKED)                         
    //////////////////////////////////////////////////////////////////////*/

    /// @dev [hi 128] = active SUN tokens | [lo 128] = index (1e32‑scaled).
    uint256 private packedIndexAndActive;

    /// @dev [hi 128] = oath (MOON‑value) | [lo 128] = pool (MOON‑value).
    uint256 private packedPoolAndOath;

    /// @dev Ephemeral “global” bundle to pass between helpers.
    struct GlobalMemory {
        uint128 pool;   // total value currently held by vault
        uint128 oath;   // total value owed to active SUN members
        uint128 index;  // cumulative owed value/share (1e32‑scaled)
        uint128 active; // total SUN tokens held by active SUN members
    }

    /*//////////////////////////////////////////////////////////////////////
                           DYNAMIC LISTS & CURSORS                          
    //////////////////////////////////////////////////////////////////////*/

    /// @dev Tokens whose pairs should be swapped through (pending ≥ MIN_SWAP_BACK).
    address[] private swapQueue;

    /// @dev Rays ready to be distributed to SUN members.
    address[] private brightRays;

    /// @dev Active SUN members (round‑robin radiation processor).
    address[] private activeMembers;

    /// @dev Cursor for `activeMembers` round‑robin.
    uint256 public activeMembersCursor;

    /*//////////////////////////////////////////////////////////////////////////
                              PRECOMPUTED SELECTORS
    //////////////////////////////////////////////////////////////////////////*/

    /// @dev Precomputed selectors for gas savings.
    bytes4 constant SEL_BALANCEOF     = bytes4(keccak256("balanceOf(address)"));         // ERC-20 style balanceOf(owner)
    bytes4 constant SEL_V1_tokenAddr  = bytes4(keccak256("tokenAddress()"));             // Uniswap V1: tokenAddress()
    bytes4 constant SEL_TOKEN0        = bytes4(keccak256("token0()"));                   // token0()
    bytes4 constant SEL_TOKEN1        = bytes4(keccak256("token1()"));                   // token1()    
    bytes4 constant SEL_BALANCEOF6909 = bytes4(keccak256("balanceOf(address,uint256)")); // ERC‑6909 style balanceOf(owner,id)
    bytes4 constant SEL_GETRESERVES   = bytes4(keccak256("getReserves()"));              // Uniswap V2: getReserves()
    bytes4 constant SEL_GETPAIR       = bytes4(keccak256("getPair(address,address)"));   // Ask factory for pair   

    /*//////////////////////////////////////////////////////////////////////
                               REENTRANCY GUARDS                          
    //////////////////////////////////////////////////////////////////////*/

    /// @dev Reentrancy guard state: 1 = unlocked, 2 = locked. Never write zero (gas savings)
    uint256 private constant _UNLOCKED = 1;
    uint256 private constant _LOCKED   = 2;

    /// @dev Storage slot for the guard (initialized to unlocked).
    uint256 private _reentrancyStatus = _UNLOCKED;

    /// @notice Reentrancy guard using a dedicated storage slot (sload/sstore).
    /// @dev
    /// - Uses non-zero states (1↔2) to avoid clearing slot.
    /// - Contract-wide single-entry guard: an external `nonReentrant` function
    ///   cannot `external`-call another `nonReentrant` one in the same tx.
    /// - Pattern: check-effects-interactions still applies inside the body.
    modifier nonReentrant() {
        require (_reentrancyStatus == _UNLOCKED, "Reentrancy");
        _reentrancyStatus = _LOCKED;
        _;
        _reentrancyStatus = _UNLOCKED;
    }

    /*//////////////////////////////////////////////////////////////////////////
                                   CONSTRUCTOR
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Initializes Moon: mints full supply to deployer, wires SUN/Vault, and seeds SUN accounting.
    /// @dev Scales `supply` and `sunSupply` by 1e18; requires non-zero key addrs and `v2FactoryFee <= 10_000` BPS.
    ///      Caches factory/fee, marks Moon/SUN/Vault as ineligible for reflections, seeds SUN accounting,
    ///      enlists sunDeployer in the active rotation, and emits the initial {Transfer}.
    /// @param supply             Whole-token MOON amount to mint to deployer (unscaled; 18 decimals applied).
    /// @param verifiedV2Factory  Canonical V2 factory used to recognize taxable pairs.
    /// @param v2FactoryFee       Factory swap fee in basis points (e.g., 30 = 0.30%).
    /// @param sunAddress         SUN ERC-20 used for distributions.
    /// @param vaultAddress       Vault that holds rays.
    /// @param sunDeployer        Initial SUN holder to seed reflection index.
    /// @param sunSupply          Whole-token SUN credited to `sunDeployer` (unscaled; 18 decimals applied).
    constructor(
        uint256  supply,
        address  verifiedV2Factory,
        uint24   v2FactoryFee,
        address  sunAddress,
        address  vaultAddress,
        address  sunDeployer,
        uint256  sunSupply
    )
    {
        // ──────────────────────────── Sanity checks ────────────────────────────
        // Require all critical external addresses (factory, SUN, Vault) to be set.
        require(
            verifiedV2Factory != address(0) &&
            sunAddress        != address(0) &&
            sunDeployer       != address(0) &&
            vaultAddress      != address(0),
            "zero address"
        );

        // Ensure AMM fee (in BPS) is not larger than 100% (10_000 BPS).
        require(v2FactoryFee <= FEE_DENOMINATOR, "fee too large");

        // Bound the unscaled MOON and SUN supplies so that, once multiplied by 1e18,
        // they can still be safely packed into the internal uint112 fields used elsewhere.
        require(supply    <= type(uint112).max / 1e18 &&
                sunSupply <= type(uint112).max / 1e18, "Supply too large");
        
        // ──────────────────────── Immutable configuration ───────────────────────
        // Save addresses/fee knobs used for pair detection & AMM math.
        factory        = verifiedV2Factory;                // Canonical (taxable) V2 factory
        sun            = sunAddress;                       // SUN token used for payouts
        vault          = vaultAddress;                     // Custody for rays
        totalSupply    = supply * 1e18;                    // Scale to 18 decimals
        totalSunSupply = sunSupply * 1e18;                 // Scale to 18 decimals
        feeBps         = v2FactoryFee;                     // e.g., 30 for 0.30%
        feeMul         = uint24(FEE_DENOMINATOR - feeBps); // e.g., 9_970 for 0.30%

        // ─────────────────────────── Mint MOON to deployer ──────────────────────
        // Mint the entire MOON supply to the deployer (`msg.sender`).
        balances[msg.sender] = totalSupply;

        // Cache the deployer as a known class-1 MOON holder (regular holder, not a pair).
        // (micro-gas: avoids first-touch classification on their first transfer)
        moonClass[msg.sender] = 1;

        // Standard ERC-20 Transfer event for the initial mint.
        emit Transfer(address(0), msg.sender, totalSupply);

        // ────────────────────────── Seed SUN bookkeeping ────────────────────────
        // Add the initial SUN holder to the active rotation list.
        activeMembers.push(sunDeployer);

        // Mark MOON, SUN, and Vault as class-2 for SUN eligibility (ineligible).
        // - MOON contract itself (no dividends to the token contract)
        // - SUN token contract
        // - Vault (custody contract)
        members[address(this)].class = 2;
        members[sunAddress].class    = 2;
        members[vaultAddress].class  = 2;

        // Initialize the global dividend index & active SUN supply:
        //   index   = 0 (no value distributed yet)
        //   active  = totalSunSupply (all initial SUN held by `sunDeployer`)
        writeIndexActive(0, uint128(totalSunSupply));

        // Initialize the `sunDeployer` member record:
        //   class   = 1 (eligible holder)
        //   status  = 2 (in activeMembers rotation)
        writeMember(sunDeployer, 0, 0, 1, 2);

        // Initialize DEAD as ineligible for emissions.
        //   class   = 2 (ineligible)
        writeMember(DEAD, 0, 0, 2, 0);

    }

    /*//////////////////////////////////////////////////////////////////////////
                                ERC-20 — VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Return MOON balance of `owner`.
    /// @dev Can revert only when part of a deceptive swap.
    function balanceOf(address owner) public view override returns (uint256) {
        require(_unlocked(owner), "Moon: Pair locked. Call skim()");
        return balances[owner];
    }

    /// @notice Return allowance from `owner` to `spender`.
    function allowance(address owner, address spender) public view override returns (uint256) {
        return allowances[owner][spender];
    }

    /// @notice Returns the number of tokens currently in the swap queue.
    function swapQueueLength() external view returns (uint256) {
        return swapQueue.length;
    }

    /// @notice Returns the number of rays currently marked as bright rays.
    function brightRaysLength() external view returns (uint256) {
        return brightRays.length;
    }

    /// @notice Returns the number of active SUN members in the rotation.
    function activeMembersLength() external view returns (uint256) {
        return activeMembers.length;
    }

    /// @notice Returns the current global pool and oath values (MOON-value terms).
    function getPoolOath() external view returns (uint128 pool, uint128 oath) {
        (pool, oath) = readPoolOath();
    }

    /// @notice Returns the current global dividend index and active SUN supply.
    function getIndexActive() external view returns (uint128 index, uint128 active) {
        (index, active) = readIndexActive();
    }

    /// @notice Returns the stored member record for a given SUN holder.
    /// @dev Exposes the persisted fields of the Member struct from storage.
    /// @param a The SUN holder’s address.
    /// @return pastIndex   Last index checkpoint for this member (1e32-scaled).
    /// @return uncollected Accrued but unclaimed MOON-value credit.
    /// @return class       Eligibility class (1 = eligible, 2 = ineligible).
    /// @return status      List status code (0 = none, 1 = pending removal, 2 = active).
    function getMember(address a)
        external
        view
        returns (uint128 pastIndex, uint112 uncollected, uint8 class, uint8 status)
    {
        (pastIndex, uncollected, class, status) = readMember(a);
    }

    /// @notice Returns the stored ray accounting data for a given paired token.
    /// @dev Provides both persisted fields and live Vault balance/decoded quotes.
    /// @param  token The address of the paired token (ray) to inspect.
    /// @return pair            Verified V2 pair that contains MOON and this token.
    /// @return reserve         Credited Vault reserve for this token.
    /// @return liveVaultBal    Current on-chain Vault balance for this token.
    /// @return pending         Pending MOON earmarked for swap-back.
    /// @return swapStatus      Swap queue status.
    /// @return brightStatus    Bright-rays list status.
    /// @return thisZero        True if MOON is token0 in the pair.
    /// @return decodedQuote    Committed price quote (MOON per token, 1e38-scaled).
    /// @return candidateQuote  Candidate intra-block high quote (1e38-scaled).
    /// @return updateBlock     Block number of last quote update.
    function getRay(address token)
        external
        view
        returns (
            address pair,
            uint112 reserve,
            uint256 liveVaultBal,
            uint112 pending,
            uint8   swapStatus,
            uint8   brightStatus,
            bool    thisZero,
            uint256 decodedQuote,
            uint256 candidateQuote,
            uint64  updateBlock
        )
    {
        Ray memory r;
        r.self = token;
        (,liveVaultBal) = _safeBalanceOf(token, vault);
        (r.pair) = readRay0(r.self);
        (r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero) = readRay1(r.self);
        (r.quote, r.candidateQuote, r.updateBlock) = readRay2(r.self);
        return (
            r.pair,
            r.reserve,
            liveVaultBal,
            r.pending,
            r.swapStatus,
            r.brightStatus,
            r.thisZero,
            r.quote,
            r.candidateQuote,
            r.updateBlock
        );
    }

    /*//////////////////////////////////////////////////////////////////////////
                    ERC-20 — MUTATIVE (ALLOWANCE & TRANSFERS)
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Approve `spender` to transfer up to `amount` MOON on caller’s behalf.
    /// @dev Emits an {Approval} event.
    function approve(address spender, uint256 amount)
        external 
        override
        returns (bool)
    {
        _approve(msg.sender, spender, amount);
        return true;
    }

    /// @notice Transfer `amount` MOON from msg.sender to `to`.
    /// @dev Triggers tax logic when interacting with class-2 V2 pairs.
    function transfer(address to, uint256 amount)
        external
        override
        nonReentrant
        returns (bool)
    {
        _transfer(msg.sender, to, amount);
        return true;
    }

    /// @notice Move `amount` MOON from `from` to `to` using caller’s allowance.
    /// @dev Deducts allowance and emits {Transfer} & {Approval} events.
    function transferFrom(address from, address to, uint256 amount)
        external
        override
        nonReentrant
        returns (bool)
    {
        uint256 currentAllowance = allowances[from][msg.sender];
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                allowances[from][msg.sender] = currentAllowance - amount;
            }
            emit Approval(from, msg.sender, currentAllowance - amount);
        }
        _transfer(from, to, amount);
        return true;
    }

    /*//////////////////////////////////////////////////////////////////////////
                            ERC-20 — INTERNAL MUTATORS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Set `spender`'s allowance over `owner`'s tokens to `amount`.
    /// @dev Internal helper, emits an {Approval} event.
    function _approve(address owner, address spender, uint256 amount) internal {
        allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /// @notice Permanently destroys `amount` of MOON from `from`, reducing the total supply.
    /// @dev
    /// Behavior:
    ///  • Updates storage under `unchecked` (safe after guards).  
    ///  • Emits the ERC-20 canonical {Transfer} to the zero address.
    /// @param from   The address whose balance is reduced (often `address(this)`).
    /// @param amount The amount of MOON to destroy (18-decimals).
    function _burn(address from, uint256 amount) internal {
        require(balances[from] >= amount);
        unchecked {
            balances[from] -= amount;
            totalSupply    -= amount;
        }
        emit Transfer(from, address(0), amount); // ERC-20 canonical burn signal
    }

    /// @notice Internal untaxed transfer helper — moves MOON without any classification or hooks.
    /// @dev
    ///  • Performs only balance updates and emits the standard {Transfer} event.  
    ///  • Skips all taxation, swap-back, and radiation logic.  
    ///  • Reverts if `from` lacks sufficient balance.  
    /// @param from   Source address.
    /// @param to     Destination address (may be any non-zero address).
    /// @param amount Amount of MOON to move (18-decimals).
    function _transferExempt(address from, address to, uint256 amount) internal {
        require(to != address(0));
        require(balances[from] >= amount);

        unchecked {
            balances[from] -= amount;
            balances[to]   += amount;
        }

        emit Transfer(from, to, amount);
    }

    /*//////////////////////////////////////////////////////////////////////////
                        EXTERNAL ENTRYPOINTS (USER / SELF)
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Claims caller’s SUN emissions and opportunistically advances maintenance.
    /// @dev If eligible, settles the caller via `_emitRay()`, then attempts one swap-back and
    ///      runs the radiation loop before committing updated aggregates. Calling is optional;
    ///      emissions accrue automatically.
    function collect() external nonReentrant {
        // Snapshot caller and their membership record.
        Member memory m;
        m.self = msg.sender;
        (m.pastIndex, m.uncollected, m.class, m.status) = readMember(m.self);

        // Snapshot global aggregates (pool/oath/index/active) for this maintenance pass.
        (uint128 pool, uint128 oath)  = readPoolOath();
        (uint128 index, uint128 active) = readIndexActive();
        GlobalMemory memory g = GlobalMemory(pool, oath, index, active);

        // If the caller is an eligible SUN holder, try to settle their pending value.
        if (m.class == 1) {
            Ray memory r;
            (g, r) = _emitRay(g, r, m);
            if (r.self != address(0)) {
                writeRay1(r.self, r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero);
            }
        }

        // Opportunistic maintenance: try one swap-back (skip none) and advance payouts.
        g = _swapBack(g, address(0));
        g = _radiate(g);
        _commitFromG(g);
    }

    /// @notice Thin wrapper that is nonReentrant and delegates to the internal implementation.
    function manuallyReclassify(address addr) external nonReentrant 
        returns (uint8 moonC, uint8 sunC)
    {
        return _manuallyReclassify(addr);
    }

    /// @notice Manually fund a ray with MOON (adds to that ray’s pending and updates value).
    /// @dev External wrapper; simply delegates to the internal implementation.
    ///      Callable by anyone. Transfer from the caller to this contract is untaxed.
    ///      Does not require a Ray with V2 MOON pair initialized. 
    function manuallyFundRay(address ray, uint256 amount) external nonReentrant {
        _manuallyFundRay(ray, amount);
    }

    /// @notice SUN transfer hook that keeps MOON’s accounting correct.
    /// @dev Only callable by `sun`. Respects MOON's reentrancy window. 
    ///      Delegates full bookkeeping to `_transferSun()` using
    ///      pre-transfer balances for fair accrual.
    /// @param from    SUN holder sending tokens.
    /// @param to      SUN holder receiving tokens.
    /// @param fromBal `from` holder’s SUN balance before the transfer (1e18-scaled).
    /// @param toBal   `to` holder’s SUN balance before the transfer (1e18-scaled).
    /// @param amount  SUN amount moved (1e18-scaled).
    function transferSun(
        address from,
        address to,
        uint256 fromBal,
        uint256 toBal,
        uint256 amount
    ) external {
        // Restrict caller to the configured SUN contract.
        require(msg.sender == sun, "Can only be called by SUN");

        // Respect Moon’s reentrancy window.
        require(_reentrancyStatus == _UNLOCKED ,"Reentrancy");

        _transferSun(from, to, fromBal, toBal, amount);
    }

    /*//////////////////////////////////////////////////////////////////////////
                         TRANSFER ENGINE (MOON TAX LOGIC)
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Core MOON transfer routine with pair‑aware taxation.
    /// @dev
    /// - Applies 3% tax on verified V2 swaps; all other movements are untaxed.
    /// - Tax is routed to `this` and attributed to the ray; then one swap‑back
    ///   and a radiation step are opportunistically executed.
    /// - Sending to `DEAD` performs a hard burn and returns early.
    /// @param from   Sender address.
    /// @param to     Recipient address (non‑zero).
    /// @param amount MOON amount to move.
    function _transfer(address from, address to, uint256 amount) internal {
        // Basic guards
        require(to != address(0), "ERC20: transfer to zero address");
        require(balances[from] >= amount, "ERC20: Balance insufficient");

        // Burning path (official sink)
        if (to == DEAD) {
            _burn(from, amount);
            return;
        }

        // Classify: verified‑pair swap (taxed) vs everything else (untaxed)
        (bool taxed, Ray memory r) = _transferType(amount, from, to);

        if (taxed) {
            // Split to recipient and protocol tax
            uint256 tax     = (amount * SWAP_TAX) / 1e18;
            uint256 postTax = amount - tax;

            unchecked {
                balances[from]          -= amount;
                balances[to]            += postTax;
                balances[address(this)] += tax;
            }
            emit Transfer(from, to, postTax);
            emit Transfer(from, address(this), tax);

            // Attribute tax to the ray (may enqueue for swap‑back)
            _updatePending(r, tax);

            // Opportunistic maintenance: one swap‑back (skip current ray) + radiation
            (uint128 pool, uint128 oath)  = readPoolOath();
            (uint128 index, uint128 active) = readIndexActive();
            GlobalMemory memory g = GlobalMemory(pool, oath, index, active);

            // Performs system maintenance.
            g = _swapBack(g, r.self);
            g = _radiate(g);

            // Defensive re‑read of active supply, then commit
            _commitFromG(g);
        } else {
            unchecked {
                balances[from] -= amount;
                balances[to]   += amount;
            }
            emit Transfer(from, to, amount);
        }
    }

    /// @notice Classifies an address for MOON‑pair semantics (tax scope).
    /// @dev
    /// - Returns 2 iff `a` is the canonical V2 pair (from `factory`) that
    ///   contains MOON; otherwise 1.
    /// - On first positive identification, caches ray token + orientation,
    ///   wires `pairs[a].ray`, and emits {RayInitialized}.
    /// - All probes are gas‑capped; failures degrade to class 1.
    /// @param a Address to classify.
    /// @return c 2 = verified V2 MOON pair; 1 = regular holder/other.
    function _getMoonClass(address a) internal returns (uint8 c) {
        // Cached
        c = moonClass[a];
        if (c != 0) return c;

        // EOAs are regular
        if (a.code.length == 0) { c = 1; moonClass[a] = c; return c; }

        // token0()/token1() probe
        (bool ok0, address t0) = _probeToken(a, SEL_TOKEN0, 40000);
        if (!ok0) { c = 1; moonClass[a] = c; return c; }
        (bool ok1, address t1) = _probeToken(a, SEL_TOKEN1, 40000);
        if (!ok1) { c = 1; moonClass[a] = c; return c; }

        // Must include MOON
        if (t0 != address(this) && t1 != address(this)) {
            c = 1; moonClass[a] = c; return c;
        }

        // Factory confirmation
        (, address official) = _probeGetPair(t0, t1, 40000);
        if (official != a) { c = 1; moonClass[a] = c; return c; }

        // Initialize ray state (pair + orientation)
        Ray memory r;
        r.pair = a;

        if      (t1 == address(this)) { r.self = t0; r.thisZero = false; } // MOON is token1
        else if (t0 == address(this)) { r.self = t1; r.thisZero = true;  } // MOON is token0

        pairs[r.pair].ray = r.self;
        moonClass[a] = 2;

        (r.reserve, r.pending, r.swapStatus, r.brightStatus,) = readRay1(r.self);
        writeRay0(r.self, a);
        writeRay1(r.self, r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero);

        emit RayInitialized(r.self);
        return 2;
    }

    /// @notice Distinguishes taxed swaps from untaxed LP mints/burns/off‑pair transfers.
    /// @dev
    /// - If neither side is a verified MOON pair → untaxed.
    /// - If any reserve is zero (bootstrap) → untaxed.
    /// - Opposite‑sign deltas in (A,M) or unchanged A → swap (taxed).
    /// - Otherwise apply a proportionality window (~±20%); outside → swap,
    ///   inside → LP mint/burn (untaxed) with a temporary `swapLock`.
    /// Note: for mint or burn to be properly identified, MOON must be sent second.
    ///       For burns this happens automatically as long as the other token has a 
    ///       smaller contract address than MOON. Hence MOON's large address.
    /// @param amount MOON amount moved.
    /// @param from   Sender.
    /// @param to     Recipient.
    /// @return taxed True if swap (taxed); false otherwise.
    /// @return r     Ray context (pair, token, reserves, orientation).
    function _transferType(
        uint256 amount,
        address from,
        address to
    )
        internal
        returns (
            bool taxed,
            Ray memory r
        )
    {
        if (amount == 0) return (false, r);

        uint8 classFrom = _getMoonClass(from);
        uint8 classTo   = _getMoonClass(to);

        // Neither touches a verified pair ⇒ untaxed
        if (!(classFrom == 2 || classTo == 2)) {
            return (false, r);
        }

        // Resolve ray + orientation + reserves
        r.pair = (classFrom == 2) ? from : to;
        r.self = pairs[r.pair].ray;
        (r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero) = readRay1(r.self);

        (bool okR, uint112 r0, uint112 r1, /*uint32 ts*/) = _probeReserves(r.pair, 40000);
        if (!okR) return (true, r); // Broken pair ⇒ taxed

        r.ra = r.thisZero ? _cap112(r1) : _cap112(r0); 
        r.rm = r.thisZero ? _cap112(r0) : _cap112(r1); 

        // Reconcile any prior swapLock
        uint256 bm = balances[r.pair]; // MOON live balance
        if (pairs[r.pair].swapLock) {
            // Tax the untaxed MOON in the pair
            // While swapLock is true, (bm - rm) amount was falsely untaxed.
            if (bm > r.rm){
                uint256 tax = (bm - r.rm) * SWAP_TAX / 1e18;
                _transferExempt(r.pair, address(this), tax);
                _updatePending(r, tax);
            }
            pairs[r.pair].swapLock = false;
        }

        // Live A balance
        (bool okB, uint256 ba) = _safeBalanceOf(r.self, r.pair); // other‑token live bal
        if (!okB) return (true, r); // Broken token ⇒ taxed

        // Adjust MOON balance directionally after this transfer
        if      (to   == r.pair) bm = _satAdd(bm, amount); // M→A swap or mint
        else if (from == r.pair) bm = _satSub(bm, amount); // A→M swap or burn

        // Bootstrap guard
        if (r.ra == 0 || r.rm == 0) return (false, r);

        // Sign test (opposite signs ⇒ swap); unchanged A ⇒ swap
        if (!_sameSign(ba, r.ra, bm, r.rm) || ba == r.ra) {
            return (true, r);
        }

        // Proportionality (~±20%) — outside window ⇒ swap
        uint256 da = ba > r.ra ? ba - r.ra : r.ra - ba; // Difference between ba and ra
        uint256 dm = bm > r.rm ? bm - r.rm : r.rm - bm; // Difference between bm and rm
        unchecked {
            // Cross terms for the ratio comparison: da/dm = r.ra/r.rm  ⇔  da*r.rm = dm*r.ra
            uint256 a = da * r.rm;
            uint256 b = dm * r.ra;

            // Scale once and compare to 6/5 (1.2) and 4/5 (0.8) bounds.
            uint256 a5 = a * 5;

            // Out of bounds if a/b > 1.2  or  a/b < 0.8
            if (a5 > b * 6 || a5 < b * 4) return (true, r);
        }

        // Inside window ⇒ LP mint/burn (untaxed); engage lock until completion
        pairs[r.pair].swapLock = true;
    }

    /// @notice Accrues MOON tax to a ray and enqueues it for swap‑back when thresholded.
    /// @dev
    /// - `pending` saturates to uint112.
    /// - Enqueues once when `pending ≥ MIN_SWAP_BACK`.
    /// - If the ray is SUN, burn the tax immediately (do not queue).
    /// @param tax Newly collected MOON.
    function _updatePending(Ray memory r, uint256 tax) internal {
        if (r.self == sun) {_burn(address(this), tax); return;}
        r.pending = _cap112(r.pending + tax);
        if (r.pending >= MIN_SWAP_BACK && r.swapStatus == 0) {
            swapQueue.push(r.self);
            r.swapStatus = 2; // in list
        }
        writeRay1(r.self, r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero);
    }

    /// @notice Read‑only guard used by `balanceOf` to enforce swap‑lock semantics.
    /// @dev
    /// - While `swapLock` is set, verifies that the (balance - reserve) are the same
    ///   sign for each token. If not, returns false (caller should `skim`).
    /// - Returns true when unlocked or probes fail (fail‑open).
    /// Note: SwapLock is only enabled when transferType identifies an LP action (Mint/Burn)
    ///       This function ensures that the action is really an LP action and not a swap.
    ///       This function should never return false outside of a malicious swap.
    /// @param pair The pair address to check.
    /// @return Whether the pair is safe/unlocked for balance queries.
    function _unlocked(address pair) internal view returns (bool){
        bool swapLock = pairs[pair].swapLock;
        if (!swapLock) return true;

        Ray memory r;
        r.pair = pair;
        r.self = pairs[r.pair].ray;
        (r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero) = readRay1(r.self);

        // Stored reserves
        (bool okR, uint112 r0, uint112 r1, /*uint32 ts*/) = _probeReserves(pair, 40000);
        if (!okR) return true;

        // Map to (A,M)
        r.ra = r.thisZero ? _cap112(r1) : _cap112(r0);
        r.rm = r.thisZero ? _cap112(r0) : _cap112(r1);

        // Live balances
        uint256 bm = balances[pair];
        (bool ok, uint256 ba) = _safeBalanceOf(r.self, pair);
        if (!ok) return true;

        // If signs still match, it's safe; otherwise block
        if (_sameSign(ba, r.ra, bm, r.rm)) return true;
        return false;
    }


    /*//////////////////////////////////////////////////////////////////////////
                              SWAPBACK (QUEUE & SWAP)
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Attempts at most one swap-back from the queue, then revalues the ray.
    /// @dev
    /// - Picks a ray pseudo-randomly, pruning small/invalid entries on the way.
    /// - Reads reserves, computes a safe `amountIn` (appreciation-coverage guard
    ///   + small impact guard), and performs a bounded self-call swap.
    /// - On success: decrements `pending`, re-probes reserves, revalues the ray,
    ///   and updates global aggregates.
    /// - On failure: removes the ray from the queue and returns.
    /// @param skipRay Optional ray to avoid (the ray in the user’s current taxed swap).
    function _swapBack(GlobalMemory memory g, address skipRay)
        internal
        returns (GlobalMemory memory)
    {
        // Early exit if nothing to do
        uint256 len = swapQueue.length;
        if (len == 0) return g;

        // Pseudo-random starting point.
        uint256 cursor = block.prevrandao + activeMembersCursor;

        Ray memory r;
        bool found;

        // Candidate selection + lazy pruning (bounded attempts)
        for (uint256 attempts = 0; attempts < 6; ++attempts) {
            len = swapQueue.length;
            if (len == 0) return g;
            cursor = (cursor + 1) % len;

            r.self = swapQueue[cursor];

            // Skip the ray currently used by the calling swap
            if (r.self == skipRay) {
                if (len == 1) return g;
                continue;
            }

            // Load packed ray fields
            (r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero) = readRay1(r.self);

            // Cull entries below threshold
            if (r.pending < MIN_SWAP_BACK) {
                _removeFromList(swapQueue, cursor);
                writeRay1(r.self, r.reserve, r.pending, 0, r.brightStatus, r.thisZero);

                // If queue emptied, we’re done; otherwise continue with element swapped into `cursor`
                len = swapQueue.length;
                if (len == 0) return g;
                continue;
            }

            // Resolve pair and cached quotes for downstream logic
            (r.quote, r.candidateQuote, r.updateBlock) = readRay2(r.self);
            r.pair = readRay0(r.self);

            found = true;
            break;
        }
        if (!found) return g;

        // Probe reserves (drop from queue if probe fails or 0 reserves)
        (bool okR, uint112 r0, uint112 r1, /*uint32 ts*/) = _probeReserves(r.pair, 40000);
        if (!okR || r0 == 0 || r1 == 0) {
            _removeFromList(swapQueue, cursor);
            writeRay1(r.self, r.reserve, r.pending, 0, r.brightStatus, r.thisZero);
            return g;
        }
        r.ra = r.thisZero ? r1 : r0;  // other token reserve
        r.rm = r.thisZero ? r0 : r1;  // MOON reserve

        //  A) Leave enough pending to cover appreciation tax after the swap
        uint256 maxInAppreciation = _maxInForAppreciation(r);
        //  B) Keep price impact no greater than SWAP_TAX
        uint256 maxInFee = (r.rm * SWAP_TAX) / 1e18;

        // Combine guards and clamp to availability
        uint256 maxIn    = maxInAppreciation <= maxInFee ? maxInAppreciation : maxInFee;
        uint256 amountIn = r.pending <= maxIn ? r.pending : maxIn;

        // Too small → drop from queue and update new price
        if (amountIn < MIN_SWAP_BACK) {
            _removeFromList(swapQueue, cursor);
            r.swapStatus = 0;
            g = _updateValue(g, r);
            return g;
        }

        // Execute swap via bounded self-call
        bytes memory swapCalldata = abi.encodeWithSelector(
            this.__swapWithPair.selector,
            r.pair,
            r.thisZero,
            amountIn,
            r.rm,
            r.ra
        );

        (bool ok, ) = address(this).call{gas: SWAPBACK_CALL_GAS}(swapCalldata);

        if (ok) {
            // Swap succeeded — shrink pending and optionally dequeue
            r.pending = r.pending - uint112(amountIn);
            if (r.pending < MIN_SWAP_BACK && r.swapStatus == 2) {
                _removeFromList(swapQueue, cursor);
                r.swapStatus = 0;
            }

            // Re-probe reserves (best effort)
            (okR, r0, r1, /*uint32 ts*/) = _probeReserves(r.pair, 40000);
            if (okR) {
                r.ra = r.thisZero ? r1 : r0;
                r.rm = r.thisZero ? r0 : r1;
            } // If probe fails, use old reserves

            // Revalue and update global aggregates
            g = _updateValue(g, r);
            return g;

        } else {
            // Swap failed — remove from queue
            _removeFromList(swapQueue, cursor);
            writeRay1(r.self, r.reserve, r.pending, 0, r.brightStatus, r.thisZero);
            return g;
        }
    }

    
    /// @notice Computes the max MOON-in that keeps pending sufficient to pay appreciation tax post-swap.
    /// @dev
    /// Goal:
    /// - Choose `x ≤ r.pending` so that after swapping `x`, the remaining `pending` can still
    ///   cover the appreciation tax that would be owed if the ray’s MOON‑denominated value
    ///   increases using the *post‑swap* reserves and quote.
    /// Notes:
    /// - Considers pair fee, pair bonus (portion left in the pool), and any uncredited tokens
    ///   already in the Vault for this ray.
    /// - Uses saturating math and defensive guards; never reverts. Returns a ceil’d `x`.
    /// @param r Ray snapshot (expects `rm`, `ra`, `reserve`, `quote`, `pending`, `self`).
    /// @return x Max MOON-in to swap now while preserving coverage.
    function _maxInForAppreciation(Ray memory r) internal view returns (uint256 x) {
        // Unpack & early guards
        uint256 P = r.pending;
        if (P == 0) return 0;

        uint256 M = r.rm;
        uint256 A = r.ra;
        if (M == 0 || A == 0) return 0;

        // Live Vault balance of token (uncredited portion considered as part of new value)
        (, uint256 B) = _safeBalanceOf(r.self, vault);

        // Shorthands (locals are cheap; immutables/consts already are)
        uint256 WAD = 1e18;
        uint256 D   = FEE_DENOMINATOR;  // 10_000
        uint256 F   = feeMul;           // ≤ 10_000
        uint256 K   = APPRECIATION_TAX; // 0.20e18

        // Pair bonus and complement
        uint256 bBonusW = PAIR_BONUS;          // 0.25e18
        uint256 gammaW  = WAD - bBonusW;       // compile-time fold; safe

        // Pending scaling vs reserves, prior credited value in MOON terms
        // pW = ceil(P * WAD / M) — safe to compute directly (P*WAD < 2^256)
        uint256 pW;
        unchecked { pW = (P * WAD + (M - 1)) / M; }

        uint256 vq      = _mulDivDown(r.reserve, r.quote, 1e38);
        uint256 kBetaUp = _mulDivUp(K, vq, M);

        // Constant term with up-bias (unsigned sign+magnitude)
        uint256 lhs   = _mulDivDown(K, B, A);       // cache: used twice
        uint256 rhs   = _satAdd(kBetaUp, pW);
        bool    negC  = lhs < rhs;
        uint256 absC  = negC ? (rhs - lhs) : (lhs - rhs);

        // Helper pieces for coefficients
        uint256 FBoverA = _mulDivDown(F, B, A);
        // Fgamma = floor(F * gammaW / WAD) — safe (F*gammaW < 2^256)
        uint256 Fgamma;
        unchecked { Fgamma = (F * gammaW) / WAD; }

        uint256 FBplus = _satAdd(FBoverA, Fgamma);

        // Quadratic/linear coefficients (WAD units, up-biased)
        // aW = floor(bBonusW * F / D) — safe (product < 2^256)
        uint256 aW = (bBonusW * F) / D;
        // KFoverD cached once; may saturate inside _mulDivDown (that’s fine)
        uint256 KFoverD = _mulDivDown(K, FBplus, D);
        aW = _satAdd(aW, KFoverD);

        uint256 bWpos = _satAdd(WAD, lhs);        // lhs was floor(K*B/A)
        bWpos         = _satAdd(bWpos, KFoverD);  // reuse

        uint256 sTot  = _satAdd(pW, kBetaUp);

        // neg = ceil( ceil(sTot * bBonusW / WAD) * F / D )
        uint256 tmp   = _mulDivUp(sTot, bBonusW, WAD);
        uint256 neg   = _mulDivUp(tmp, F, D);

        uint256 bW = (neg >= bWpos) ? 0 : (bWpos - neg);

        // Solve for t (normalized by WAD), using ceil where needed to preserve up-bias
        uint256 tW = 0;

        if (aW == 0) {
            if (negC) {
                tW = _mulDivUp(absC, WAD, bW); // may saturate if bW==0 → OK (clamped later)
            }
        } else {
            bool safe_b2   = (bW == 0) || (bW <= type(uint256).max / bW);
            bool safe_a4   = (aW <= type(uint256).max / 4);
            bool safe_four = safe_a4 && (absC == 0 || ((aW << 2) <= type(uint256).max / absC));
            bool safe_den  = (aW <= type(uint256).max / 2);

            if (safe_b2 && safe_four && safe_den) {
                uint256 b2;           unchecked { b2 = bW * bW; }
                uint256 four_a_abs_c; unchecked { four_a_abs_c = (aW << 2) * absC; }

                uint256 disc;
                if (!negC) {
                    disc = (b2 >= four_a_abs_c) ? (b2 - four_a_abs_c) : 0;
                } else {
                    disc = (type(uint256).max - b2 < four_a_abs_c) ? type(uint256).max : (b2 + four_a_abs_c);
                }

                uint256 s = _isqrt(disc);

                if (s > bW) {
                    uint256 num; unchecked { num = s - bW; }
                    uint256 den; unchecked { den = aW << 1; }
                    tW = _mulDivUp(num, WAD, den);
                }
            } else {
                if (negC) {
                    tW = _mulDivUp(absC, WAD, bW);
                }
            }
        }

        // Convert normalized t to MOON-in, ceil, and clamp to pending
        x = _mulDivUp(tW, M, WAD);
        if (x > P) x = P;
    }



    /// @notice Internal router for MOON→token swaps on a verified V2 pair (self-call only).
    /// @dev
    /// - Transfers `amountIn` MOON into the pair, recomputes the *actual* input,
    ///   applies factory fee and the pair bonus, and routes output directly to the Vault.
    /// - Reverts on zero output to avoid no-op swaps.
    /// - Orientation-aware: if MOON is token0, outputs token1; otherwise token0.
    /// @param pair       V2 pair to swap against.
    /// @param thisZero   True if MOON is token0 in the pair.
    /// @param amountIn   Intended MOON input (ledger transfer).
    /// @param reserveIn  Pre-swap MOON reserve (orientation-correct).
    /// @param reserveOut Pre-swap other-token reserve (orientation-correct).
    function __swapWithPair(
        address pair,
        bool    thisZero,
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) external {
        // Self-call only
        require(msg.sender == address(this), "Moon: self-call only");

        // Disable swapLock
        if (pairs[pair].swapLock) {
            pairs[pair].swapLock = false;
        }

        // Router-style ledger move: push MOON to the pair
        _transferExempt(address(this), pair, amountIn);

        // Compute the actual input observed by the pair
        uint256 realIn = _satSub(balances[pair], reserveIn);

        // V2 x*y=k with factory fee
        uint256 inWithFee   = realIn * uint256(feeMul);
        uint256 numerator   = inWithFee * reserveOut;
        uint256 denominator = reserveIn * FEE_DENOMINATOR + inWithFee;
        uint256 amountOut   = (denominator == 0) ? 0 : (numerator / denominator);

        // Apply pair bonus (leave a fraction in the pool)
        amountOut = amountOut * (1e18 - PAIR_BONUS) / 1e18;
        require(amountOut != 0);

        // Execute the swap; send proceeds to the Vault
        if (thisZero) {
            IUniswapV2Pair(pair).swap(0, amountOut, vault, new bytes(0));
        } else {
            IUniswapV2Pair(pair).swap(amountOut, 0, vault, new bytes(0));
        }
    }

    /*//////////////////////////////////////////////////////////////////////////
                            LIGHT ENGINE (RADIATE/EMIT)
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Processes active SUN members within a fixed gas stipend and advances payouts.
    /// @dev
    /// - Round‑robin over `activeMembers` from `activeMembersCursor`.
    /// - Removes stale entries (no longer active)
    /// - Calls {_emitRay} for active entries, then persists the new cursor.
    function _radiate(GlobalMemory memory g)
        internal
        returns (GlobalMemory memory)
    {
        // Open gas window and snapshot cursor (monotonic measure: start - gasleft() increases)
        uint256 start = gasleft();
        uint256 i = activeMembersCursor;

        Ray memory r;
        Member memory m;

        // Iterate while we have gas budget
        while (start - gasleft() < RADIATE_GAS_LIMIT) {
            uint256 lenNow = activeMembers.length;
            if (lenNow == 0) break;             // nothing to do
            if (i >= lenNow) i = 0;             // wrap if list shrank

            // Load member snapshot
            m.self = activeMembers[i];
            (m.pastIndex, m.uncollected, m.class, m.status) = readMember(m.self);

            if (m.status != 2) {
                // Remove from rotation (swap‑and‑pop); do not advance i (new element sits at i)
                _removeFromList(activeMembers, i);
                writeMember(m.self, m.pastIndex, m.uncollected, m.class, 0);
            } else {
                // Active entry: attempt an emission, then advance
                (g, r) = _emitRay(g, r, m);
                unchecked { ++i; }
            }
        }

        // Persist new credited reserves
        if (r.self != address(0)) {
            writeRay1(r.self, r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero);
        }

        // Persist cursor for next pass
        activeMembersCursor = i;
        return g;
    }

    /// @notice Settles a SUN holder’s MOON‑valued claim by releasing tokens from the Vault.
    /// @dev
    /// - Accrues the caller’s pending MOON‑value using Δindex and their SUN balance at the start
    ///   of the interval, folding any previously stored `uncollected`.
    /// - Pays out against “bright” ray buckets. A member is typically paid from a single token
    ///   type per call; if that bucket cannot cover the scaled claim, a new bucket is selected.
    /// - Payouts respect current coverage (pool/oath). Accounting advances as if the full
    ///   unscaled value were settled, while the member actually receives `unscaled × pool/oath`.
    /// - Grief‑resistant by design: Whether the token transfer succeeds or not, the global pool 
    ///   is reduced by the realized value removed from the bucket. When the transfer succeeds, 
    ///   the member’s claim (`m.uncollected`) and the global (`g.oath`) are debited proportionally.
    /// - List maintenance is O(1). This function only writes ray state immediately when it has to
    ///   delist; otherwise the caller of {_emitRay} persists the last touched ray with a single
    ///   packed write after the loop.
    /// @param r acts as a reusable cursor: it may persist across calls, and is only 
    ///   written back to storage when the selected bucket is fully drained or delisted.
    function _emitRay(GlobalMemory memory g, Ray memory r, Member memory m)
        internal
        returns (GlobalMemory memory, Ray memory)
    {
        // Accrue the member’s claim for the current index window.
        // Index is monotonic; wrapping is allowed in unchecked math.
        uint128 deltaIndex;
        unchecked { deltaIndex = g.index - m.pastIndex; }

        if (m.class != 1) return (g, r);
        if (g.oath == 0)  return (g, r);

        // Resolve the member’s SUN balance at the beginning of this index interval
        if (deltaIndex != 0) {
            (/*ok*/, m.balance) = _safeBalanceOf(sun, m.self);
            uint256 earned = _divIndex(uint256(m.balance) * uint256(deltaIndex));
            m.uncollected  = _cap112(earned + uint256(m.uncollected));
        }
        if (m.uncollected < MIN_EMIT) return (g, r);

        // Seed for pseudo‑random bucket order.
        uint256 seed;
        if (r.self == address(0)) {
            seed = uint256(keccak256(abi.encodePacked(block.prevrandao, m.self)));
        }

        // Settle against at most MAX_PAYOUT_TOKENS buckets to bound work per call.
        uint256 iter;
        while (m.uncollected >= MIN_EMIT && iter < MAX_PAYOUT_TOKENS) {
            unchecked { ++iter; }
            if (g.pool < MIN_EMIT || g.oath < MIN_EMIT) break;

            // Cursor resets to a new ray only when the current one delists or is too small.
            if (r.self == address(0)) {
                uint256 len = brightRays.length;
                if (len == 0) break;

                // Xorshift to mix the seed between selections.
                unchecked {
                    seed ^= (seed << 13);
                    seed ^= (seed >> 7);
                    seed ^= (seed << 17);
                }

                // Choose a bucket and fetch its persisted accounting.
                r.cursor = seed % len;
                r.self   = brightRays[r.cursor];

                (r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero) = readRay1(r.self);
                (r.quote, r.candidateQuote, r.updateBlock) = readRay2(r.self);

                // Lazy prune: if it is no longer marked “in‑list”, drop it now.
                if (r.brightStatus != 2) {
                    _removeFromList(brightRays, r.cursor);
                    writeRay1(r.self, r.reserve, r.pending, r.swapStatus, 0, r.thisZero);
                    r.self = address(0);
                    continue;
                }
            }

            // Scale the member’s unscaled claim by the live coverage ratio.
            // The member receives: paid = unscaled × (pool / oath)
            // while accounting burns the full unscaled amount from `m.uncollected` and `g.oath`.
            uint256 scaled = _mulDivDown(uint256(m.uncollected), uint256(g.pool), g.oath);

            // Convert scaled MOON‑value into whole tokens available from this ray,
            // using the committed quote. 
            uint256 payAmt = (r.quote == 0) ? 0 : _mulDivDown(scaled, 1e38, r.quote);
            if (payAmt == 0) {
                r.self = address(0);
                continue;
            }

            // Clamp to the credited reserve (never over‑draw a bucket).
            if (payAmt > r.reserve) payAmt = r.reserve;

            // Compute the value to be removed from the pool at the committed quote.
            uint256 tokenValBefore = _mulDivDown(uint256(r.reserve), r.quote, 1e38);
            r.reserve              = _cap112(_satSub(uint256(r.reserve), payAmt));
            uint256 tokenValAfter  = _mulDivDown(uint256(r.reserve), r.quote, 1e38);
            uint256 rayDeltaVal    = tokenValBefore - tokenValAfter; // realized value

            // Attempt release from the Vault (bounded gas, tolerant of non‑standard ERC‑20s).
            // Zero‑length return is considered success; revert or false is failure.
            (bool ok, ) = vault.call{gas: 150_000}(
                abi.encodeWithSelector(
                    IVault.releaseToMember.selector,
                    r.self,
                    payAmt,
                    m.self
                )
            );

            // When the transfer succeeds, burn the member’s unscaled claim and reduce global oath
            if (ok) {
                uint256 payValUnscaled = (g.pool == 0)
                    ? 0
                    : _mulDivDown(rayDeltaVal, uint256(g.oath), uint256(g.pool));
                if (payValUnscaled > m.uncollected) payValUnscaled = m.uncollected;

                g.oath        = _satSub128(g.oath, _cap128(payValUnscaled));
                m.uncollected = _cap112(_satSub(uint256(m.uncollected), payValUnscaled));
            }

            // The global pool is debited by the realized value regardless of transfer outcome.
            g.pool = _satSub128(g.pool, _cap128(rayDeltaVal));

            // If the bucket’s residual value falls below the emission floor, delist it immediately.
            // Remove its residual contribution from the pool and clear its bright flag.
            if (tokenValAfter < MIN_EMIT) {
                _removeFromList(brightRays, r.cursor);
                r.brightStatus = 0;
                g.pool         = _satSub128(g.pool, _cap128(tokenValAfter));
                writeRay1(r.self, r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero);
                r.self = address(0);
            }
        }
        writeMember(m.self, g.index, m.uncollected, m.class, m.status);

        return (g, r);
    }


    /*//////////////////////////////////////////////////////////////////////////
                    SUN ACCOUNTING & ELIGIBILITY (TRACKING)                     
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Bookkeeps a SUN transfer so index accrual, rotation, and active supply stay correct.
    /// @dev
    /// - Uses **pre‑transfer** balances (supplied by SUN) to accrue each side fairly at the
    ///   current index, then snapshots both to close the window.
    /// - Maintains the active member list (eligible = balance ≥ MIN_SUN_RADIATE) 
    ///   and updates the global count of eligible SUN (`active`) only when class boundaries are crossed.
    /// @param from    SUN holder sending tokens.
    /// @param to      SUN holder receiving tokens.
    /// @param fromBal Pre‑transfer SUN balance of `from` (1e18‑scaled).
    /// @param toBal   Pre‑transfer SUN balance of `to` (1e18‑scaled).
    /// @param amount  SUN amount moved (1e18‑scaled).
    function _transferSun(address from, address to, uint256 fromBal, uint256 toBal, uint256 amount) internal { 
        // No-op guard: zero amount or self-transfer has no accounting effect.
        if (amount == 0 || from == to) return;

        Member memory f;
        Member memory t;

        f.self    = from;
        f.balance = fromBal;
        t.self    = to;
        t.balance = toBal;    

        (f.pastIndex, f.uncollected, f.class, f.status) = readMember(f.self);
        (t.pastIndex, t.uncollected, t.class, t.status) = readMember(t.self);

        // First-touch classification if unknown. Only class-1 holders accrue & rotate.
        if (f.class == 0) f = _getSunClass(f);
        if (t.class == 0) t = _getSunClass(t);

        (uint128 index, uint128 active) = readIndexActive();

        // Accrue “uncollected” using the **pre-transfer** balances at this index.
        if (f.class == 1) f = _recordUncollected(f, index); 
        if (t.class == 1) t = _recordUncollected(t, index);

        // Snapshot both members to the current index to close this accrual window.
        f.pastIndex = index;
        t.pastIndex = index;

        // Calculate post transfer balances.
        unchecked {
            f.balance -=amount;
            t.balance +=amount;
        }
        
        // Maintain active-member rotation: class-1 with balance ≥ MIN_SUN_RADIATE are listed.
        if (f.class == 1) f.status = _updateList(activeMembers, f.self, f.status, f.balance >= MIN_SUN_RADIATE);
        if (t.class == 1) t.status = _updateList(activeMembers, t.self, t.status, t.balance >= MIN_SUN_RADIATE);

        // Update global count of eligible (class-1) SUN tokens used by index math.
        _updateActiveToken(f.class, t.class, amount, index, active); 

        writeMember(f.self, f.pastIndex, f.uncollected, f.class, f.status);
        writeMember(t.self, t.pastIndex, t.uncollected, t.class, t.status);
    }

    /// @notice Classifies an address for SUN eligibility (1 = eligible EOA/holder, 2 = ineligible pool).
    /// @dev
    /// - EOAs → class 1.
    /// - Pool‑like contracts (V2/V3 token0(), Uniswap V1 tokenAddress(), ERC‑6909 balanceOf) → class 2.
    /// - All probes are gas‑capped STATICCALLs; failures degrade to class 1.
    /// - View‑only helper; does not write to storage.
    /// Note: all other contracts can hold SUN and receive reflections.
    ///       Pair‑like contracts are only excluded to avoid wasting rays that would get trapped in them.
    /// @param m Member snapshot with `self` set.
    /// @return m Same struct with `class` updated in memory.
    function _getSunClass(Member memory m)
        internal view
        returns (Member memory)
    {
        address member = m.self;

        // EOAs eligible by default
        if (member.code.length == 0) { m.class = 1; return m; }

        // V2/V3‑style pools expose token0()
        (bool ok0, address t0) = _probeToken(member, SEL_TOKEN0, 50000);
        if (ok0 && t0 != address(0)) { m.class = 2; return m; }

        // Uniswap V1 pairs expose tokenAddress()
        (bool ok2, address t1) = _probeToken(member, SEL_V1_tokenAddr, 50000);
        if (ok2 && t1 != address(0)) { m.class = 2; return m; }

        // ERC‑6909 multi‑token style exposes balanceOf(address,uint256)
        (bool ok3, /*uint256*/) = _probeBalanceOf6909(member, address(1), 0, 50000);
        if (ok3) { m.class = 2; return m; }

        m.class = 1;
        return m;
    }

    /// @notice Accrues a member’s uncollected MOON‑valued claim up to `index`.
    /// @dev
    /// - If balance > 0 and `index` moved, adds round‑to‑nearest( balance * Δindex / 1e32 ).
    /// - Does not change `pastIndex`; caller should snapshot after accrual.
    /// - Caps to uint112 to preserve storage packing.
    /// @param m     Member snapshot (expects `balance` and `pastIndex` set).
    /// @param index Current global index (1e32‑scaled).
    /// @return m    Member with `uncollected` updated (capped).
    function _recordUncollected(Member memory m, uint128 index) internal pure returns (Member memory){
        if (m.balance != 0 && index != m.pastIndex) {
            uint128 delta;
            // Index is monotonic; wrapping allowed in unchecked math
            unchecked { delta = index - m.pastIndex; }

            // Newly earned unscaled value (rounded to nearest via _divIndex)
            uint256 add = _divIndex(uint256(m.balance) * uint256(delta));
            m.uncollected = _cap112(m.uncollected + add);
        }
        return m;
    }

    /// @notice Adjusts global eligible SUN supply when tokens enter/exit class‑1.
    /// @dev
    /// - Increases `active` when tokens move into class‑1; decreases when they leave it.
    /// - No change for 1→1 or 2→2 moves.
    /// - Writes `(index, active)` only when `active` changes to save gas.
    /// @param classFrom Previous class (1 = eligible).
    /// @param classTo   New class (1 = eligible).
    /// @param amount    SUN amount moved (1e18‑scaled).
    /// @param index     Current global index (persisted alongside `active`).
    /// @param active    Snapshot of current eligible supply to adjust/persist.
    function _updateActiveToken(
        uint8 classFrom,
        uint8 classTo,
        uint256 amount,
        uint128 index,
        uint128 active
    ) internal {
        uint256 oldActive = active; // avoid unnecessary writes

        if (classTo == 1 && classFrom != 1) {
            // Entering class‑1
            active = _satAdd128(active, uint128(amount));        
        } else if (classFrom == 1 && classTo != 1) {
            // Leaving class‑1
            active = _satSub128(active, uint128(amount));    
        }

        // Persist only if changed
        if (active != oldActive) {
            writeIndexActive(index, active);
        }
    }

    /*//////////////////////////////////////////////////////////////////////////
                             VALUE & QUOTE TRACKING 
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Revalues a ray (paired token) against the Vault and updates pool/oath/index.
    /// @dev
    /// - Refresh credited reserve from the Vault and update the committed quote.
    /// - Compute prior value (oldReserve @ oldQuote), then apply appreciation coverage:
    ///   burn from `r.pending` first, then withhold reserve for any unpaid portion.
    /// - Maintain list membership (bright rays) and apply Δvalue to (pool/oath/index).
    /// - Persist updated packed fields (reserve/pending/status/orientation).
    /// @return g Updated global aggregates.
    function _updateValue(
        GlobalMemory memory g,
        Ray memory          r
    ) internal returns (GlobalMemory memory){

        // Previous credited reserve; refresh from Vault (safe read, capped)
        uint256 oldReserve = r.reserve;
        (bool ok, uint256 balance) = _safeBalanceOf(r.self, vault);
        if (ok) r.reserve = _cap112(balance);
        
        // Update quote; capture the previously committed quote for oldVal
        uint256 oldQuote;
        (r, oldQuote) = _updateQuote(r);

        // Prior value at (oldReserve, oldQuote); then apply appreciation coverage
        uint256 oldVal = _mulDivDown(oldReserve, oldQuote, 1e38);
        uint256 newVal;
        (r, newVal) = _applyAppreciationTax(r, oldVal);

        // Maintain bright‑ray membership by current value
        uint8 oldStatus = r.brightStatus;
        r.brightStatus = _updateList(brightRays, r.self, r.brightStatus, newVal > MIN_EMIT);

        // Apply Δvalue:
        // - If active: positive deltas lift pool, oath and index; negatives reduce pool only.
        // - If delisted now: remove its previous contribution immediately.
        int256 deltaVal = int256(newVal); 

        if (r.brightStatus == 2) {
            if (oldStatus == 2) deltaVal -= int256(oldVal);
            if (deltaVal >= 0) {
                uint128 inc = _cap128(uint256(deltaVal));
                g.pool = _satAdd128(g.pool, inc);
                if (g.active > 0) { // if active = 0 only pool increases
                    g.oath = _satAdd128(g.oath, inc);
                    uint256 indexInc = uint256(inc) * 1e32 / g.active;
                    unchecked { g.index += uint128(indexInc); } // index can wrap
                }
            } else {
                g.pool = _satSub128(g.pool, _cap128(uint256(-deltaVal))); // oath and index unaffected  
            }
        } else if (r.brightStatus == 1 && oldStatus == 2) { // Removed from brightRays
            g.pool = _satSub128(g.pool, _cap128(oldVal)); 
        } 
        
        writeRay1(r.self, r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero);
        return g;
    }

    /// @notice Updates a ray’s committed quote using spot and intra‑block highs.
    /// @dev
    /// Policy:
    /// - If spot > committed: lift immediately (quote=candidate=spot).
    /// - Same block: candidate tracks the running max.
    /// - New block: commit last block’s high to `quote`, seed `candidate` with current spot.
    /// Quotes are 1e38‑scaled MOON‑per‑token and encoded/decoded via Uint256Float96.
    /// Note: This system prevents artificial price dips that increase ray emission amount.
    /// @return r         Ray snapshot with refreshed quote fields.
    /// @return prevQuote The committed quote before this update.
    function _updateQuote(Ray memory r)
        internal
        returns (Ray memory, uint256 prevQuote)
    {
        prevQuote = r.quote;

        // 1e38‑scaled spot = rm/ra (if both non‑zero), then encode/decode to align rounding
        uint256 spot;
        if (r.ra != 0 && r.rm != 0) {
            spot = r.rm * 1e38 / r.ra; // No overflow risk
        } else return (r, prevQuote); 

        // Encode and Decode for standardization.
        uint96 spot96 = Uint256Float96.encode(spot);
        spot          = Uint256Float96.decode(spot96);

        // Immediate lift on higher spot (or when previous quote is zero)
        if (spot > prevQuote || prevQuote == 0) {
            r.quote          = spot;                  
            r.candidateQuote = spot;               
            r.updateBlock    = uint64(block.number);
            writeRay2(r.self, r.quote, r.candidateQuote, r.updateBlock);
            return (r, prevQuote);
        }

        // Same block: keep a running intra‑block max in candidate
        if (uint256(r.updateBlock) == block.number) {
            if (spot > r.candidateQuote) {
                r.candidateQuote = spot;
                writeRay2(r.self, r.quote, r.candidateQuote, r.updateBlock);
            }
            return (r, prevQuote);
        }

        // New block: commit last block’s high; seed candidate with current spot
        r.quote          = r.candidateQuote;
        r.candidateQuote = spot;
        r.updateBlock    = uint64(block.number);
        writeRay2(r.self, r.quote, r.candidateQuote, r.updateBlock);

        return (r, prevQuote);
    }

    /// @notice Applies appreciation coverage: pay for positive value increases or withhold reserve.
    /// @dev
    /// - If the ray’s MOON‑denominated value rose vs `oldVal`, charge
    ///   `due = ceil(APPRECIATION_TAX * (newVal - oldVal) / 1e18)`.
    /// - Pay from `r.pending` first (burning MOON). Any unpaid portion is “withheld” by
    ///   reducing the credited reserve so that unpaid gains are not counted.
    /// - Returns the final `newVal` after withholding (uses the committed quote).
    function _applyAppreciationTax(
        Ray memory r,
        uint256 oldVal
    )
        internal
        returns (Ray memory, uint256 newVal)
    {   
        if (r.quote == 0) return(r, 0);

        // Tax is only applied to positive delta
        newVal = _mulDivDown(uint256(r.reserve), r.quote, 1e38);
        if (newVal <= oldVal) return (r, newVal);

        uint256 dValue;
        unchecked { dValue = newVal - oldVal; }

        // Required coverage for this event
        uint256 unpaidValue = _mulDivUp(APPRECIATION_TAX, dValue, 1e18);

        if (r.pending != 0){
            // Burn from pending, clamped by pending and contract balance
            uint256 payNow = (unpaidValue <= r.pending) ? unpaidValue : r.pending;
            uint256 moonBal = balances[address(this)];
            payNow = payNow <= moonBal ? payNow : moonBal;

            r.pending = r.pending - uint112(payNow);
            _burn(address(this), payNow);

            unpaidValue = _satSub(unpaidValue, payNow);
        }

        // Withhold any unpaid portion by reducing credited reserve
        if (unpaidValue != 0) {
            uint256 unpaidValueTokens = _mulDivUp(unpaidValue, 1e18, APPRECIATION_TAX);
            uint256 unpaidTokens      = _mulDivUp(unpaidValueTokens, 1e38, r.quote);
            r.reserve = uint112(_satSub(r.reserve, unpaidTokens));
        }

        // Recompute value from the final credited reserve
        newVal = _mulDivDown(r.reserve, r.quote, 1e38);
        return (r, newVal);
    }

    /*//////////////////////////////////////////////////////////////////////////
                     LIST MANAGEMENT (LIST / DELIST / INIT)
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Maintains membership flags for a rotation list (add / mark‑for‑removal).
    /// @dev
    /// Status codes (shared convention):
    ///   0 = not in list
    ///   1 = pending removal (will be physically removed later when index is known)
    ///   2 = in list
    ///
    /// Policy:
    /// - If `shouldBe` and not already 2: ensure presence (push if 0) and set to 2.
    /// - If not `shouldBe` and currently 2: mark as 1 (defer actual removal to keep this path O(1)).
    /// - Returns the new status to be persisted by the caller.
    /// @param list      Target storage array.
    /// @param self      Address whose membership is being updated.
    /// @param status    Current persisted status for `self`.
    /// @param shouldBe  Whether `self` should be in the list given current conditions.
    /// @return          New status code for `self`.
    function _updateList(
        address[] storage list,
        address self,
        uint8 status,
        bool shouldBe
    ) internal returns (uint8) {
        if (shouldBe && status != 2) {
            // Ensure presence when transitioning to "in list"
            if (status == 0) {
                list.push(self);
            }
            status = 2;
        } else if (!shouldBe && status == 2) {
            // Mark for later physical removal
            status = 1;
        }
        return status;
    }  

    /// @notice Removes element at index `i` from `list` in O(1) via swap‑and‑pop (order not preserved).
    /// @dev Caller must ensure `i < list.length`. Reverts if array is empty.
    /// @param list The storage array to modify.
    /// @param i    Index to remove.
    function _removeFromList(address[] storage list, uint256 i) internal {
        uint256 last = list.length - 1;

        if (i != last) {
            list[i] = list[last];
        }

        // Manually decrement list.length to avoid clearing slot (gas savings)
        assembly {
            let lenSlot := list.slot
            sstore(lenSlot, sub(sload(lenSlot), 1))
        }
    }

    /*//////////////////////////////////////////////////////////////////////////
                                 MANUAL MAINTENANCE 
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Re-probes MOON pair detection and SUN eligibility for `addr`, reconciling accounting if eligibility flips.
    /// @dev
    /// MOON side:
    /// - Verified pairs are sticky (remain class 2). Otherwise clear cached class and re‑probe via `_getMoonClass`.
    /// SUN side:
    /// - If currently not ineligible, recompute advisory class in memory.
    /// - If it becomes ineligible (class 2): recycle value back into index and remove from activeMembers list
    /// - Returns latest observed classes: `moonC` (1|2) and `sunC` (1|2).
    /// @param addr Address to reclassify.
    /// @return moonC Latest MOON class after (optional) re-probe (2 = verified pair; 1 = regular).
    /// @return sunC  Latest SUN eligibility (2 = ineligible; 1 = eligible).
    function _manuallyReclassify(address addr)
        internal
        returns (uint8 moonC, uint8 sunC)
    {
        /*───────────────────────  MOON CLASS (pair detection)  ───────────────────────*/
        // Keep verified pairs sticky; otherwise clear and re‑probe.
        uint8 cachedMoon = moonClass[addr];
        if (cachedMoon < 2) {
            moonClass[addr] = 0;           // clear only when not a verified pair
            moonC = _getMoonClass(addr);   // re‑classify (2 = verified V2 pair; else 1)
        } else {
            moonC = cachedMoon;            // leave sticky classification as‑is
        }

        /*────────────────────────  SUN CLASS (eligibility)  ──────────────────────────*/
        Member memory m;
        m.self = addr;
        (m.pastIndex, m.uncollected, m.class, m.status) = readMember(m.self);

        uint8 oldClass = m.class;

        // Recompute advisory SUN class in memory (no write unless it becomes 2).
        if (m.class != 2)  {
            m = _getSunClass(m);
            sunC = m.class; 
        } else {
            // Already ineligible; return current state.
            sunC = 2;
        }

        if (oldClass == 1 && m.class == 2) {
            // Update active SUN supply and remove from rotation.
            (uint128 index, uint128 active) = readIndexActive();
            (,m.balance) = _safeBalanceOf(sun, m.self);  // live SUN balance (safe read)
            _updateActiveToken(oldClass, 2, m.balance, index, active);
            (, active) = readIndexActive();

            // Recycle value back into index
            m = _recordUncollected(m, index);
            if (active != 0){
                uint256 indexInc = uint256(m.uncollected) * 1e32 / active;
                unchecked { index += uint128(indexInc); } // index can wrap
                writeIndexActive(index, active);
            } else { // If for some reason active is 0, oath is decremented instead.
                (uint128 pool, uint128 oath) = readPoolOath();
                writePoolOath(pool, _satSub128(oath, _cap128(uint256(m.uncollected))));
            }
            m.uncollected = 0;
            m.pastIndex = index;

            // Delist from activeMembers rotation
            m.status = _updateList(activeMembers, m.self, m.status, false);
        } 
        writeMember(m.self, m.pastIndex, m.uncollected, m.class, m.status);
    }

    /// @notice Adds MOON to a ray’s `pending` and optionally updates value/enqueue for swap-back.
    /// @dev
    /// - Pulls `amount` from caller to this contract (untaxed internal transfer).
    /// - Increases `pending` (saturating). If the ray’s pair is initialized and reserves exist:
    ///   • Enqueue for swap-back when `pending ≥ MIN_SWAP_BACK` and not already queued.
    ///   • Update value/quotes and global aggregates, then commit.
    /// - If pair is uninitialized or probes fail, only the packed ray fields are updated.
    /// @param ray    Ray token address.
    /// @param amount MOON amount to add to `pending`.
    function _manuallyFundRay(address ray, uint256 amount) internal {
        // Ray cannot be MOON, SUN, a class 2 pair, or an EOA.
        require(ray != address(this)
             && ray.code.length > 0
             && pairs[ray].ray == address(0)
             && ray != sun 
             && amount != 0, "Moon: invalid ray or 0 amount");

        // Pull MOON into the contract (untaxed internal transfer)
        _transferExempt(msg.sender, address(this), amount);

        // Initialize local ray context
        Ray memory r;
        r.self = ray;
        (r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero) = readRay1(r.self);

        // Add to pending (saturating); queuing decision happens below
        r.pending = _cap112(r.pending + amount);

        // If the pair is initialized, try to update value and queue if appropriate
        bool valueUpdated;
        r.pair = readRay0(r.self);
        if (r.pair != address(0)) {
            (bool okR, uint112 r0, uint112 r1, /*uint32 ts*/) = _probeReserves(r.pair, 40000);
            if (okR && r0 != 0 && r1 != 0) {
                r.ra = r.thisZero ? r1 : r0;  // other token reserve
                r.rm = r.thisZero ? r0 : r1;  // MOON reserve

                // Enqueue for swap-back once threshold is met and not already listed
                if (r.pending >= MIN_SWAP_BACK && r.swapStatus == 0) {
                    swapQueue.push(r.self);
                    r.swapStatus = 2; // in list
                }

                // Refresh value + globals, then commit
                (uint128 pool,  uint128 oath)   = readPoolOath();
                (uint128 index, uint128 active) = readIndexActive();
                GlobalMemory memory g = GlobalMemory(pool, oath, index, active);

                (r.quote, r.candidateQuote, r.updateBlock) = readRay2(r.self);

                g = _updateValue(g, r);
                valueUpdated = true;

                // Opportunistic maintenance: try one swap-back (skip none) and advance payouts.
                g = _swapBack(g, address(0));
                g = _radiate(g);
                _commitFromG(g);
            }
        }

        if (!valueUpdated) {
            writeRay1(r.self, r.reserve, r.pending, r.swapStatus, r.brightStatus, r.thisZero);
        }
    }

    /*//////////////////////////////////////////////////////////////////////////
                                  STORAGE HELPERS
    //////////////////////////////////////////////////////////////////////////*/

    // Bit masks
    uint256 private constant _MASK_64   = (uint256(1) << 64)  - 1;
    uint256 private constant _MASK_96   = (uint256(1) << 96)  - 1;
    uint256 private constant _MASK_112  = (uint256(1) << 112) - 1;
    uint256 private constant _MASK_128  = (uint256(1) << 128) - 1;

    /// Base slot of: mapping(address => Member) internal members;
    function _membersBase() private pure returns (bytes32 s) {
        assembly ("memory-safe") { s := members.slot }
    }

    /// Base slot of: mapping(address => Ray) internal rays;
    function _raysBase() private pure returns (bytes32 s) {
        assembly ("memory-safe") { s := rays.slot }
    }

    /// Slot of: uint256 private packedIndexAndActive;   // [hi 128]=active | [lo 128]=index
    function _idxActSlot() private pure returns (bytes32 s) {
        assembly ("memory-safe") { s := packedIndexAndActive.slot }
    }

    /// Slot of: uint256 private packedPoolAndOath;      // [hi 128]=oath   | [lo 128]=pool
    /// (Kept the function name your helpers already reference: _poolOathSlot)
    function _poolOathSlot() private pure returns (bytes32 s) {
        assembly ("memory-safe") { s := packedPoolAndOath.slot }
    }

    /// @dev keccak256(abi.encode(key, base))
    function _map(bytes32 base, address key) private pure returns (bytes32 slot) {
        assembly ("memory-safe") {
            mstore(0x00, key)
            mstore(0x20, base)
            slot := keccak256(0x00, 0x40)
        }
    }

    /// @dev Computes the base storage slot for `members[who]` (slot0 of the Member struct).
    function _memberSlot0(address who) private pure returns (bytes32 s0) {
        s0 = _map(_membersBase(), who);
    }

    /// @dev Computes the base storage slot for `rays[token]` (slot0 of the Ray struct).
    function _raySlot0(address token) private pure returns (bytes32 s0) {
        s0 = _map(_raysBase(), token);
    }

    /// @dev Computes slot1 of `rays[token]` (holds reserve/pending/status/orientation fields).
    function _raySlot1(address token) private pure returns (bytes32 s1) {
        bytes32 s0 = _raySlot0(token);
        unchecked { s1 = bytes32(uint256(s0) + 1); }
    }

    /// @dev Computes slot2 of `rays[token]` (holds packed quote96/candidateQuote96/updateBlock).
    function _raySlot2(address token) private pure returns (bytes32 s2) {
        bytes32 s0 = _raySlot0(token);
        unchecked { s2 = bytes32(uint256(s0) + 2); }
    }

    /// @notice Read (index, active) from `packedIndexAndActive`.
    function readIndexActive() internal view returns (uint128 index, uint128 active) {
        bytes32 s = _idxActSlot();
        uint256 w; assembly ("memory-safe") { w := sload(s) }
        index  = uint128(w);
        active = uint128(w >> 128);
    }

    /// @notice Write (index, active) to `packedIndexAndActive`.
    function writeIndexActive(uint128 index, uint128 active) internal {
        bytes32 s = _idxActSlot();
        uint256 nw = (uint256(active) << 128) | uint256(index);
        assembly ("memory-safe") { sstore(s, nw) }
    }

    /// @notice Read (pool, oath) from `packedPoolAndOath`.
    function readPoolOath() internal view returns (uint128 pool, uint128 oath) {
        bytes32 s = _poolOathSlot();
        uint256 w; assembly ("memory-safe") { w := sload(s) }
        pool   = uint128(w);
        oath = uint128(w >> 128);
    }

    /// @notice Write (pool, oath) to `packedPoolAndOath`.
    function writePoolOath(uint128 pool, uint128 oath) internal {
        bytes32 s = _poolOathSlot();
        uint256 nw = (uint256(oath) << 128) | uint256(pool);
        assembly ("memory-safe") { sstore(s, nw) }
    }

    /// @notice Read members[who].slot0 → (pastIndex:128, uncollected:112, class:8, status:8).
    /// @dev    Single-slot layout. All bits are densely packed as documented above.
    function readMember(address who)
        internal
        view
        returns (uint128 pastIndex, uint112 uncollected, uint8 class, uint8 status)
    {
        bytes32 s0 = _memberSlot0(who);
        uint256 w; assembly ("memory-safe") { w := sload(s0) }

        pastIndex   = uint128( w         & _MASK_128 );
        uncollected = uint112((w >> 128) & _MASK_112 );
        class       = uint8  ((w >> 240) & 0xFF);
        status      = uint8  ((w >> 248) & 0xFF);
    }

    /// @notice Write members[who].slot0 ← (pastIndex:128, uncollected:112, class:8, status:8).
    /// @dev    Densely packs fields and overwrites the entire word.
    function writeMember(address who, uint128 pastIndex, uint112 uncollected, uint8 class, uint8 status) internal {
        bytes32 s0 = _memberSlot0(who);

        uint256 nw =
            (uint256(pastIndex)    & _MASK_128)         |
            ((uint256(uncollected) & _MASK_112) << 128) |
            ((uint256(class)       & 0xFF)      << 240) |
            ((uint256(status)      & 0xFF)      << 248);

        assembly ("memory-safe") { sstore(s0, nw) }
    }

    /// @notice Read rays[token].slot0 → (pair).
    function readRay0(address token)
        internal
        view
        returns (address pair)
    {
        bytes32 s0 = _raySlot0(token);
        uint256 w; assembly ("memory-safe") { w := sload(s0) }
        pair = address(uint160(w));
    }

    /// @notice Write rays[token].slot0 ← (pair).
    function writeRay0(address token, address pair) internal {
        bytes32 s0 = _raySlot0(token);
        uint256 nw = uint256(uint160(pair));
        assembly ("memory-safe") { sstore(s0, nw) }
    }

    /// @notice Read rays[token].slot1 → (reserve:uint112, pending:uint112, swapStatus:uint8, brightStatus:uint8, thisZero:bool).
    /// @dev    The topmost 8 bits [248..255] are reserved and ignored.
    function readRay1(address token)
        internal
        view
        returns (uint112 reserve, uint112 pending, uint8 swapStatus, uint8 brightStatus, bool thisZero)
    {
        bytes32 s1 = _raySlot1(token);
        uint256 w; assembly ("memory-safe") { w := sload(s1) }

        reserve      = uint112( w         & _MASK_112 );
        pending      = uint112((w >> 112) & _MASK_112 );
        swapStatus   = uint8  ((w >> 224) & 0xFF);
        brightStatus = uint8  ((w >> 232) & 0xFF);
        thisZero     = ((w >> 240)        & 0xFF) != 0;
    }

    /// @notice Write rays[token].slot1 ← (reserve:uint112, pending:uint112, swapStatus:uint8, brightStatus:uint8, thisZero:bool).
    /// @dev    Preserves the topmost reserved 8-bit lane [248..255]; only updates bits [0..247].
    function writeRay1(
        address token,
        uint112 reserve,
        uint112 pending,
        uint8 swapStatus,
        uint8 brightStatus,
        bool thisZero
    ) internal {
        bytes32 s1 = _raySlot1(token);

        // Low 248 bits (everything we control)
        uint256 lw =
            (uint256(reserve)       & _MASK_112)         |
            ((uint256(pending)      & _MASK_112) << 112) |
            ((uint256(swapStatus)   & 0xFF)      << 224) |
            ((uint256(brightStatus) & 0xFF)      << 232) |
            ((thisZero ? uint256(1) : uint256(0)) << 240);

        // Preserve the reserved top 8 bits [248..255] from the existing word.
        uint256 oldW; assembly ("memory-safe") { oldW := sload(s1) }
        uint256 keepTop8 = oldW & ~((uint256(1) << 248) - 1);

        uint256 nw = keepTop8 | lw;
        assembly ("memory-safe") { sstore(s1, nw) }
    }

    /// @notice Read rays[token].slot2 → (quote:uint256, candidateQuote:uint256, updateBlock:uint64).
    /// @dev     Decodes Float96-packed quote fields into uint256 for call‑sites.
    function readRay2(address token)
        internal
        view
        returns (uint256 quote, uint256 candidateQuote, uint64 updateBlock)
    {
        bytes32 s2 = _raySlot2(token);
        uint256 w; assembly ("memory-safe") { w := sload(s2) }
        uint96 qPacked  = uint96(w & _MASK_96);
        uint96 cPacked  = uint96((w >> 96)  & _MASK_96);
        updateBlock     = uint64((w >> 192) & _MASK_64);

        quote          = Uint256Float96.decode(qPacked);
        candidateQuote = Uint256Float96.decode(cPacked);
    }

    /// @notice Write rays[token].slot2 ← (quote:uint256, candidateQuote:uint256, updateBlock:uint64).
    /// @dev     Encodes the uint256 quote fields into Float96 before packing.
    function writeRay2(address token, uint256 quote, uint256 candidateQuote, uint64 updateBlock) internal {
        bytes32 s2 = _raySlot2(token);
        uint96 qPacked = Uint256Float96.encode(quote);
        uint96 cPacked = Uint256Float96.encode(candidateQuote);

        uint256 nw = uint256(qPacked)
                   | (uint256(cPacked)     << 96)
                   | (uint256(updateBlock) << 192);
        assembly ("memory-safe") { sstore(s2, nw) }
    }

    /*//////////////////////////////////////////////////////////////////////////
                            SAFE STATIC PROBE SYSTEM
    ////////////////////////////////////////////////////////////////////////////*/

    /// @notice Probes a target contract for an `address` return value (e.g., token0/token1).
    /// @dev
    /// Behavior
    ///  • Performs a gas‑capped `STATICCALL` via {_staticProbeRaw} expecting a 32‑byte ABI word.  
    ///  • On success, decodes the low 20 bytes as an `address`.  
    ///  • On failure (revert, short/empty return, etc.), returns `(false, address(0))`.
    /// Notes
    ///  • This helper is used for various “what token is this?” checks, and never reverts.  
    ///  • It is safe against non‑standard contracts: all decoding is bounds‑checked.
    /// @param target   Contract to probe.
    /// @param selector 4‑byte function selector (e.g., `SEL_TOKEN0`, `SEL_TOKEN1`, `SEL_V1_tokenAddr`).
    /// @param gasCap   Gas limit to forward to the probe (keeps failures cheap/deterministic).
    /// @return ok      True if the call succeeded and returned at least 32 bytes.
    /// @return token   Decoded address (low 20 bytes of the first 32‑byte word) or zero on failure.
    function _probeToken(address target, bytes4 selector, uint256 gasCap)
        internal
        view
        returns (bool ok, address token)
    {
        bytes memory out;
        (ok, out) = _staticProbeRaw(target, selector, 0, 0, 0, gasCap, 32);
        if (!ok) return (false, address(0));

        // ABI returns address left‑padded in 32 bytes — take the low 20 bytes.
        assembly ("memory-safe") {
            token := and(mload(add(out, 32)), 0xffffffffffffffffffffffffffffffffffffffff)
        }
    }

    /// @notice Reads Uniswap‑V2‑style reserves from a pair via `getReserves()`.
    /// @dev
    /// Behavior
    ///  • Calls `pair.getReserves()` via a gas‑capped `STATICCALL`.  
    ///  • Expects exactly 96 bytes: (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast).  
    ///  • Returns `(false, 0, 0, 0)` on failure.  
    ///  • On success, saturates each reserve to `uint112` to guard against maliciously wide values.
    /// Security & Robustness
    ///  • Never reverts; unsuitable/misbehaving pairs simply yield `ok=false`.  
    ///  • Saturating downcasts ensure internal math cannot overflow reserve‑sized lanes.
    /// @param pair   The V2‑style pair to probe.
    /// @param gasCap Gas limit to forward to the probe.
    /// @return ok    True when a 96‑byte response was obtained.
    /// @return r0    Reserve0 (saturated to uint112).
    /// @return r1    Reserve1 (saturated to uint112).
    /// @return ts    Pair’s `blockTimestampLast` (uint32).
    function _probeReserves(address pair, uint256 gasCap)
        internal
        view
        returns (bool ok, uint112 r0, uint112 r1, uint32 ts)
    {
        bytes memory out;
        (ok, out) = _staticProbeRaw(pair, SEL_GETRESERVES, 0, 0, 0, gasCap, 96);
        if (!ok) return (false, 0, 0, 0);

        // Decode three 32‑byte words; only low bits of the first two are used post‑saturation.
        uint256 a;
        uint256 b;
        uint256 c;
        assembly ("memory-safe") {
            let ptr := add(out, 32)
            a := mload(ptr)
            b := mload(add(ptr, 32))
            c := mload(add(ptr, 64))
        }

        // Saturating downcasts (guard against malicious wide values).
        r0 = a > type(uint112).max ? type(uint112).max : uint112(a);
        r1 = b > type(uint112).max ? type(uint112).max : uint112(b);
        ts = uint32(c);
    }

    /// @notice Asks a canonical factory for a pair address via `getPair(tokenA, tokenB)`.
    /// @dev
    /// Behavior
    ///  • Performs a gas‑capped `STATICCALL` to the factory’s `getPair(a,b)`, expecting 32 bytes.  
    ///  • On success, decodes and returns the low 20 bytes as an `address`.  
    ///  • On failure, returns `(false, address(0))`.
    /// Notes
    ///  • This is used to verify that an observed pair is the official one constructed by `factory`.
    /// @param tokenA  First token of the pair (order usually irrelevant in factories).
    /// @param tokenB  Second token of the pair.
    /// @param gasCap  Gas limit to forward to the probe.
    /// @return ok     True when a 32‑byte response was obtained.
    /// @return pair   The decoded pair address (low 20 bytes) or zero on failure.
    function _probeGetPair(address tokenA, address tokenB, uint256 gasCap)
        internal
        view
        returns (bool ok, address pair)
    {
        bytes memory out;
        (ok, out) = _staticProbeRaw(
            factory,
            SEL_GETPAIR,
            uint256(uint160(tokenA)),
            uint256(uint160(tokenB)),
            2,
            gasCap,
            32
        );
        if (!ok) return (false, address(0));

        // ABI returns address left‑padded in 32 bytes — take the low 20 bytes.
        assembly ("memory-safe") {
            pair := and(mload(add(out, 32)), 0xffffffffffffffffffffffffffffffffffffffff)
        }
    }

    /// @notice Safe, gas‑capped `balanceOf(owner)` probe against an ERC‑20‑like `token`.
    /// @dev
    /// Behavior
    ///  • Calls `token.balanceOf(owner)` as a gas‑capped `STATICCALL`.  
    ///  • On success, decodes a 32‑byte word and returns it, clamped to `uint112` (reserve‑style bound).  
    ///  • On failure, returns `(false, 0)`.
    /// Notes
    ///  • Some non‑standard tokens return no/short data or revert; all cases are treated as failure.  
    ///  • Clamping to `uint112` preserves packing assumptions used elsewhere in this contract.
    /// @param token  ERC‑20‑style token to query.
    /// @param owner  Account whose balance is being probed.
    /// @return ok    True if the probe returned at least 32 bytes.
    /// @return bal   Decoded balance (clamped to `uint112`) or 0 on failure.
    function _safeBalanceOf(address token, address owner)
        internal
        view
        returns (bool ok, uint256 bal)
    {
        bytes memory out;
        (ok, out) = _staticProbeRaw(
            token,
            SEL_BALANCEOF,
            uint256(uint160(owner)),
            0,
            1,
            30000,
            32
        );
        if (!ok) return (false, 0);

        assembly ("memory-safe") { bal := mload(add(out, 32)) }
        if (bal > type(uint112).max) bal = type(uint112).max;
    }

    /// @notice ERC‑6909‑style `balanceOf(owner, id)` probe for multi‑token pools.
    /// @dev
    /// Behavior
    ///  • Calls `token.balanceOf(owner, id)` via gas‑capped `STATICCALL`.  
    ///  • On success, decodes a 32‑byte word and returns it.  
    ///  • On failure, returns `(false, 0)`.
    /// Notes
    ///  • Used purely as a detection probe for “multi‑asset” style pool contracts.  
    ///  • Never reverts; unsuitable targets just yield `ok=false`.
    /// @param token   Multi‑token contract to query.
    /// @param owner   Account whose balance is being probed.
    /// @param id      Token ID within the multi‑token contract.
    /// @param gasCap  Gas limit to forward to the probe.
    /// @return ok     True when a 32‑byte response was obtained.
    /// @return bal    Decoded balance or 0 on failure.
    function _probeBalanceOf6909(address token, address owner, uint256 id, uint256 gasCap)
        internal
        view
        returns (bool ok, uint256 bal)
    {
        bytes memory out;
        (ok, out) = _staticProbeRaw(
            token,
            SEL_BALANCEOF6909,
            uint256(uint160(owner)),
            id,
            2,
            gasCap,
            32
        );
        if (!ok) return (false, 0);

        assembly ("memory-safe") { bal := mload(add(out, 32)) }
    }

    /// @notice Uniswap V1‑style `tokenAddress()` probe (returns the ERC‑20 token held by the V1 pair).
    /// @dev Thin wrapper over {_probeToken} using `SEL_V1_tokenAddr`. See {_probeToken} for semantics.
    /// @param v1Pair The V1‑style pair to query.
    /// @param gasCap Gas limit to forward to the probe.
    /// @return ok    True if a 32‑byte response was obtained.
    /// @return token Decoded token address or zero on failure.
    function _probeV1TokenAddress(address v1Pair, uint256 gasCap)
        internal
        view
        returns (bool ok, address token)
    {
        return _probeToken(v1Pair, SEL_V1_tokenAddr, gasCap);
    }

    /// @notice Low‑level, gas‑capped `STATICCALL` helper with flexible ABI encoding and length checks.
    /// @dev
    /// Behavior
    ///  • Builds calldata for 0, 1, or 2 arguments with the provided `selector`.  
    ///  • For zero‑arg calls, first tries canonical 4‑byte selector encoding; if that fails or returns
    ///    fewer than `minLen` bytes, retries with a 32‑byte padded selector (certain odd interfaces expect this).  
    ///  • Executes a `STATICCALL` with `gasCap` forwarded.  
    ///  • If `success && ret.length >= minLen`, copies exactly `minLen` bytes into a freshly allocated buffer
    ///    and returns `(true, out)`. Otherwise returns `(false, "")`.
    /// Constraints & Conventions
    ///  • `minLen` in this codebase is always a multiple of 32 (32 or 96), enabling tight word‑wise copying.  
    ///  • This function never reverts; it is safe to use in heuristics and detection flows.
    /// @param target   Contract to call.
    /// @param selector 4‑byte function selector.
    /// @param arg0     First ABI argument (ignored when `argCount == 0`).
    /// @param arg1     Second ABI argument (used when `argCount == 2`).
    /// @param argCount Number of ABI arguments to encode: 0, 1, or 2.
    /// @param gasCap   Gas forwarded to the `STATICCALL`.
    /// @param minLen   Minimum return‑data length required for success (bytes).
    /// @return ok      True if the call succeeded and returned at least `minLen` bytes.
    /// @return out     A `bytes` buffer of length `minLen` containing the first `minLen` bytes of returndata.
    function _staticProbeRaw(
        address target,
        bytes4  selector,
        uint256 arg0,
        uint256 arg1,
        uint256 argCount,
        uint256 gasCap,
        uint256 minLen
    ) internal view returns (bool ok, bytes memory out) {
        bytes memory data;
        if (argCount == 0) {
            data = abi.encodeWithSelector(selector);              // 4-byte calldata
        } else if (argCount == 1) {
            data = abi.encodeWithSelector(selector, arg0);
        } else {
            data = abi.encodeWithSelector(selector, arg0, arg1);
        }

        bool success;
        uint256 size;

        // First attempt: copy 0 bytes on call, then copy only minLen if size is sufficient
        assembly ("memory-safe") {
            success := staticcall(gasCap, target, add(data, 0x20), mload(data), 0, 0)
            size := returndatasize()
        }

        if (argCount == 0 && (!success || size < minLen)) {
            // Retry with 32-byte padded selector
            bytes memory data32 = new bytes(32);
            assembly ("memory-safe") {
                mstore(add(data32, 32), shl(224, selector))
                success := staticcall(gasCap, target, add(data32, 0x20), 0x20, 0, 0)
                size := returndatasize()
            }
        }

        ok = success && size >= minLen;
        if (!ok) return (false, bytes(""));

        // Allocate exactly minLen and copy only that much from the return buffer
        out = new bytes(minLen);
        assembly ("memory-safe") {
            returndatacopy(add(out, 0x20), 0, minLen)
        }
    }

    /*//////////////////////////////////////////////////////////////////////////
                        INTERNAL UTILITIES (MATH & PROBES)
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Saturating subtraction – clamps at zero instead of under-flowing.
    function _satSub(uint256 a, uint256 b) internal pure returns (uint256 r) {
        unchecked { r = a > b ? a - b : 0; }
    }

    /// @notice Saturating addition – clamps at max uint256 instead of overflowing.
    function _satAdd(uint256 a, uint256 b) internal pure returns (uint256 r) {
        unchecked {
            r = a + b;
            if (r < a) {
                // Overflow happened, clamp to max
                r = type(uint256).max;
            }
        }
    }

    /// @notice Saturating subtraction – clamps at zero instead of under-flowing.
    function _satSub128(uint128 a, uint128 b) internal pure returns (uint128 r) {
        unchecked { r = a > b ? a - b : 0; }
    }

    /// @notice Saturating addition – clamps at max uint128 instead of overflowing.
    function _satAdd128(uint128 a, uint128 b) internal pure returns (uint128 r) {
        unchecked {
            r = a + b;
            if (r < a) {
                // Overflow happened, clamp to max
                r = type(uint128).max;
            }
        }
    }

    /// @notice Compare signs of (a1 - a2) and (b1 - b2) without subtracting.
    /// @dev Zero is inclusive; only false when one delta >0 and the other <0
    function _sameSign(uint256 a1, uint256 a2, uint256 b1, uint256 b2)
        internal
        pure
        returns (bool)
    {
        return (a1 >= a2 && b1 >= b2) || (a1 <= a2 && b1 <= b2);
    }

    // Floor: saturating semantics, with 512 fallback only on overflow.
    function _mulDivDown(uint256 a, uint256 b, uint256 d) internal pure returns (uint256 r) {
        unchecked {
            // Common trivials first (helps inlining + constant folding)
            if ((a | b) == 0) return 0;
            if (d == 0) return type(uint256).max;

            // Try 256-bit product; if it overflowed, bail to 512
            uint256 p = a * b;
            if (a == 0 || p / a == b) {
                return p / d; // floor
            }
        }
        // Rare: overflow -> 512-bit saturated path
        return __mulDiv512_sat(a, b, d, false);
    }

    // Ceil: saturating semantics, with 512 fallback only on overflow.
    function _mulDivUp(uint256 a, uint256 b, uint256 d) internal pure returns (uint256 r) {
        unchecked {
            if ((a | b) == 0) return 0;
            if (d == 0) return type(uint256).max;

            uint256 p = a * b;
            if (a == 0 || p / a == b) {
                uint256 q = p / d;
                // ceil (avoid wrap on MAX)
                return q + (((p % d) != 0 && q != type(uint256).max) ? 1 : 0);
            }
        }
        return __mulDiv512_sat(a, b, d, true);
    }

    /// @dev Shared 512-bit mulDiv (floor/ceil) with saturation. Never reverts.
    function __mulDiv512_sat(uint256 a, uint256 b, uint256 d, bool roundUp) private pure returns (uint256 result) {
        assembly ("memory-safe") {
            // Defensive: saturate if d == 0 (shouldn't happen due to early returns above)
            if iszero(d) {
                result := not(0)
            }
            if d {
                // 512-bit multiply: [prod1 prod0] = a * b
                let mm := mulmod(a, b, not(0))
                let prod0 := mul(a, b)
                let prod1 := sub(sub(mm, prod0), lt(mm, prod0))

                // If quotient wouldn't fit in 256 bits, saturate: (prod1 >= d)
                if iszero(gt(d, prod1)) {
                    result := not(0)
                }
                if gt(d, prod1) {
                    // Compute remainder and make division exact.
                    let rem := mulmod(a, b, d)
                    prod1 := sub(prod1, gt(rem, prod0))
                    prod0 := sub(prod0, rem)

                    // Factor powers of two out of d.
                    let twos := and(d, sub(0, d))
                    d := div(d, twos)

                    // Divide [prod1 prod0] by the factored power of two.
                    prod0 := div(prod0, twos)
                    twos := add(div(sub(0, twos), twos), 1)    // twos = 2^256 / twos
                    prod0 := or(prod0, mul(prod1, twos))

                    // Compute floor quotient q. If reduced d == 1, skip inverse.
                    let q
                    if eq(d, 1) {
                        q := prod0
                    }
                    if iszero(eq(d, 1)) {
                        // Newton-Raphson modular inverse of odd d modulo 2^256 (6 steps)
                        let inv := xor(mul(3, d), 2)
                        inv := mul(inv, sub(2, mul(d, inv)))
                        inv := mul(inv, sub(2, mul(d, inv)))
                        inv := mul(inv, sub(2, mul(d, inv)))
                        inv := mul(inv, sub(2, mul(d, inv)))
                        inv := mul(inv, sub(2, mul(d, inv)))
                        inv := mul(inv, sub(2, mul(d, inv)))
                        q := mul(prod0, inv)
                    }

                    result := q

                    // If round up: add 1 iff (remainder != 0) and result != MAX (saturate instead of wrap)
                    if roundUp {
                        result := add(result, and(gt(rem, 0), iszero(eq(result, not(0)))))
                    }
                }
            }
        }
    }

    /// @notice Caps a uint256 value down to uint128, clamping at the max if overflow.
    function _cap128(uint256 x) internal pure returns (uint128) {
        return x > type(uint128).max ? type(uint128).max : uint128(x);
    }

    /// @notice Caps a uint256 value down to uint112, clamping at the max if overflow.
    function _cap112(uint256 x) internal pure returns (uint112) {
        return x > type(uint112).max ? type(uint112).max : uint112(x);
    }

    /// @dev Integer floor sqrt with a good first guess; 7 Newton steps are enough for 256-bit.
    function _isqrt(uint256 x) internal pure returns (uint256 y) {
        if (x == 0) return 0;
        uint256 z = uint256(1) << (_log2(x) >> 1);
        unchecked {
            // 7 Newton iterations
            for (uint256 i; i < 7; ++i) { z = (z + x / z) >> 1; }
        }
        y = z;
        // Safe clamp: avoids overflow when y >= 2^128
        if (y > 0 && y > x / y) y--;
    }

    /// @dev Tiny log2 used to seed sqrt (gas-cheap).
    function _log2(uint256 x) internal pure returns (uint256 n) {
        if (x >= 2**128) { x >>= 128; n += 128; }
        if (x >= 2**64)  { x >>= 64;  n += 64;  }
        if (x >= 2**32)  { x >>= 32;  n += 32;  }
        if (x >= 2**16)  { x >>= 16;  n += 16;  }
        if (x >= 2**8)   { x >>= 8;   n += 8;   }
        if (x >= 2**4)   { x >>= 4;   n += 4;   }
        if (x >= 2**2)   { x >>= 2;   n += 2;   }
        if (x >= 2**1)   {            n += 1;   }
    }

    // Round to nearest integer: Tie is rounded down
    // Returns round( num / INDEX_DECIMALS ).
    function _divIndex(uint256 num) internal pure returns (uint256 q) {
        // q = floor(num / 1e32), r = num - q*1e32  (0 <= r < 1e32)
        q = num / INDEX_DECIMALS;
        uint256 r = num - q * INDEX_DECIMALS;

        // Compare 2*r to the denominator to avoid floating point
        uint256 twice = r * 2;

        if (twice > INDEX_DECIMALS) {
            unchecked { q += 1; } // strictly above half -> round up
        } 
        // else below half -> keep q
    }

    /// @dev commits global g values if the slots changed.
    /// Always refers to cached 'active'
    function _commitFromG(GlobalMemory memory g) internal {
        (uint128 _index, uint128 _active) = readIndexActive();
        (uint128  _pool, uint128   _oath) = readPoolOath();

        if (g.index != _index) {
            // keep the latest active; only advance index
            writeIndexActive(g.index, _active);
        }
        if (g.pool != _pool || g.oath != _oath) {
            writePoolOath(g.pool, g.oath);
        }
    }

}
        

Compiler Settings

{"viaIR":true,"remappings":[],"optimizer":{"runs":6000,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"paris","compilationTarget":{"contracts/Moon.sol":"Moon"}}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"supply","internalType":"uint256"},{"type":"address","name":"verifiedV2Factory","internalType":"address"},{"type":"uint24","name":"v2FactoryFee","internalType":"uint24"},{"type":"address","name":"sunAddress","internalType":"address"},{"type":"address","name":"vaultAddress","internalType":"address"},{"type":"address","name":"sunDeployer","internalType":"address"},{"type":"uint256","name":"sunSupply","internalType":"uint256"}]},{"type":"error","name":"BadPackedExponent","inputs":[{"type":"uint8","name":"e","internalType":"uint8"}]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RayInitialized","inputs":[{"type":"address","name":"ray","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"APPRECIATION_TAX","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"DEAD","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint24","name":"","internalType":"uint24"}],"name":"FEE_DENOMINATOR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"INDEX_DECIMALS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_PAYOUT_TOKENS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_EMIT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_SUN_RADIATE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_SWAP_BACK","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"PAIR_BONUS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"RADIATE_GAS_LIMIT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"SWAPBACK_CALL_GAS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"SWAP_TAX","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"__swapWithPair","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"bool","name":"thisZero","internalType":"bool"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"reserveIn","internalType":"uint256"},{"type":"uint256","name":"reserveOut","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"activeMembersCursor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"activeMembersLength","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"brightRaysLength","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"collect","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint24","name":"","internalType":"uint24"}],"name":"feeBps","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint24","name":"","internalType":"uint24"}],"name":"feeMul","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"index","internalType":"uint128"},{"type":"uint128","name":"active","internalType":"uint128"}],"name":"getIndexActive","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"pastIndex","internalType":"uint128"},{"type":"uint112","name":"uncollected","internalType":"uint112"},{"type":"uint8","name":"class","internalType":"uint8"},{"type":"uint8","name":"status","internalType":"uint8"}],"name":"getMember","inputs":[{"type":"address","name":"a","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"pool","internalType":"uint128"},{"type":"uint128","name":"oath","internalType":"uint128"}],"name":"getPoolOath","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"uint112","name":"reserve","internalType":"uint112"},{"type":"uint256","name":"liveVaultBal","internalType":"uint256"},{"type":"uint112","name":"pending","internalType":"uint112"},{"type":"uint8","name":"swapStatus","internalType":"uint8"},{"type":"uint8","name":"brightStatus","internalType":"uint8"},{"type":"bool","name":"thisZero","internalType":"bool"},{"type":"uint256","name":"decodedQuote","internalType":"uint256"},{"type":"uint256","name":"candidateQuote","internalType":"uint256"},{"type":"uint64","name":"updateBlock","internalType":"uint64"}],"name":"getRay","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"manuallyFundRay","inputs":[{"type":"address","name":"ray","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint8","name":"moonC","internalType":"uint8"},{"type":"uint8","name":"sunC","internalType":"uint8"}],"name":"manuallyReclassify","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"ray","internalType":"address"},{"type":"bool","name":"swapLock","internalType":"bool"}],"name":"pairs","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"sun","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"swapQueueLength","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSunSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferSun","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"fromBal","internalType":"uint256"},{"type":"uint256","name":"toBal","internalType":"uint256"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"vault","inputs":[]}]
              

Contract Creation Code

0x610140346200041657601f620063d238819003918201601f1916830191906001600160401b038311848410176200041b578160e09285926040958652833981010312620004165781519060206200005881850162000431565b828501519462ffffff948587169283880362000416576200007c6060840162000431565b946200008b6080850162000431565b9260c06200009c60a0870162000431565b9501516001600d55956001600160a01b03938085161515806200040a575b80620003fe575b80620003f2575b15620003bf57612710908183116200038b576612725dd1d243ab8085111590816200037f575b5015620003485760a0528860c0528560e052670de0b6b3a7640000808402938085048214901517156200033257600098848a558181029181830414901517156200031e576080526101009b8c52039889116200030a57610120988952338652600182528786205560038152868520600160ff1982541617905584548751908152857fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef833393a3600b5468010000000000000000811015620002f6576001810180600b55811015620002e257600b86528186200180546001600160a01b03191683861617905530855260049052858420805460ff60f01b19908116600160f11b90811790925595821685528685208054871682179055911683528483208054909416811790935560808051901b6001600160801b031916600755815282812061020160f01b905561dead81528290205551615f8b929091908362000447843960805183610e40015260a05183818161082d01526155a3015260c051838181610b9501528181610e93015281816113db015281816116cd01528181612d210152613e4d015260e05183818161029201528181610428015281816104e701528181610f88015281816127d601528181613fcf0152614f7601525182611535015251818181610348015281816110e10152614fac0152f35b634e487b7160e01b86526032600452602486fd5b634e487b7160e01b86526041600452602486fd5b634e487b7160e01b86526011600452602486fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b600052601160045260246000fd5b8a5162461bcd60e51b815260048101869052601060248201526f537570706c7920746f6f206c6172676560801b6044820152606490fd5b905089111538620000ee565b8a5162461bcd60e51b815260048101869052600d60248201526c66656520746f6f206c6172676560981b6044820152606490fd5b895162461bcd60e51b815260048101859052600c60248201526b7a65726f206164647265737360a01b6044820152606490fd5b508486161515620000c8565b508487161515620000c1565b508489161515620000ba565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620004165756fe608060408181526004918236101561001657600080fd5b600092833560e01c91826303fd2a45146117c15750816306fdde0314611763578163095ea7b3146116f157816317b5bb32146116ad57816318160ddd146116905781631d4cd5661461167157816323b872dd1461155957816324a9d853146115195781632ada259614611491578163313ce56714611475578163401ea9111461144257816343f45df714611423578163506c692d1461110557816353e1a7a0146110c55781635d9657f3146102b65781636189324b146110a2578163636c840314610f4a57816363a1089814610f2157816367ac46f314610e635781636ba980b914610e2857816370a0823114610d9c578163712bf4051461099757816384be07091461097857816394f2e4101461095c57816395d89b41146108fa57816399e37dff146108d8578163a479c94f146108b9578163a9059cbb14610870578163ba80105714610851578163c45a01551461080d578163cb8ae4da146107d6578163d73792a9146107b9578163dd62ed3e14610770578163e52253811461060a578163ebe10505146105ec578163f03fc310146102bb57508063fbaa4a2b146102b6578063fbfa77cf14610273578063fe33b3021461022a578063ff0ae962146102085763ff5f3820146101e857600080fd5b346102045781600319360112610204576020905162035b608152f35b5080fd5b5034610204578160031936011261020457602090516703782dace9d900008152f35b5090346102705760206003193601126102705760ff826001600160a01b0392836102526118f1565b168152600660205220548351928116835260a01c1615156020820152f35b80fd5b5034610204578160031936011261020457602090516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b611922565b839150346102045760a0600319360112610204576102d76118f1565b9260249182359283151584036105e857606435953033036105a6576001600160a01b0396610327888316928389526006602052868920805460ff8160a01c1661057b575b5050604435903061397b565b81875260016020528487205481808211156105705761036e91035b62ffffff7f00000000000000000000000000000000000000000000000000000000000000001690611a77565b61037a60843582611a77565b916127109081810291818304149015171561055e579061039991611a8a565b8061054f57505085965b670a688906bd8b00009788810298818a04149015171561053d57670de0b6b3a764000087980495861561048c57156104905784516103e08161183f565b878152823b1561048c57879461045e869392849389519a8b98899788967f022c0d9f0000000000000000000000000000000000000000000000000000000088528701528501527f0000000000000000000000000000000000000000000000000000000000000000166044840152608060648401526084830190611893565b03925af1908115610483575061047357505080f35b61047c9061180f565b6102705780f35b513d84823e3d90fd5b8780fd5b93949091928551906104a18261183f565b878252833b1561048c5761051d889692879389519a8b98899788967f022c0d9f0000000000000000000000000000000000000000000000000000000088528701528501527f0000000000000000000000000000000000000000000000000000000000000000166044840152608060648401526084830190611893565b03925af19081156104835750610531575080f35b61053a9061180f565b80f35b8287601186634e487b7160e01b835252fd5b61055891611a97565b966103a3565b8489601188634e487b7160e01b835252fd5b505061036e87610342565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690558a8061031b565b506014906020606494519362461bcd60e51b85528401528201527f4d6f6f6e3a2073656c662d63616c6c206f6e6c790000000000000000000000006044820152fd5b8480fd5b50503461020457816003193601126102045760209051620557308152f35b5050346102045781600319360112610204576106fe6106f9610703926106346001600d5414611945565b6002600d55610641611a34565b9033608083015260ff610684336000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b841660608701529092168385019081526001600160701b0392831660208601526001600160801b039182168552600854600754855192969390916106c7846117dd565b818116845260801c602084015281168583015260801c6060820152600160ff829651161461070b575b50505050612fb8565b61361f565b6138af565b6001600d5580f35b6107209293945061071a6119b3565b906125b5565b9290926001600160a01b03610120820151169182156106f0578361076794602084015116918301511660ff6060840151169160a060ff608086015116940151151594612e73565b388080806106f0565b5050346102045780600319360112610204578060209261078e6118f1565b61079661190c565b6001600160a01b0391821683526002865283832091168252845220549051908152f35b505034610204578160031936011261020457602090516127108152f35b50503461020457816003193601126102045760075490516001600160801b038216815260809190911c6020820152604090f35b0390f35b505034610204578160031936011261020457602090516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b5050346102045781600319360112610204576020906009549051908152f35b5050346102045780600319360112610204576020906108ad6108906118f1565b61089e6001600d5414611945565b6002600d556024359033611ab7565b6001600d555160018152f35b505034610204578160031936011261020457602090600b549051908152f35b50503461020457816003193601126102045760209051666a94d74f4300008152f35b91905034610958578260031936011261095857610809925080519161091e83611823565b82527f4d4f4f4e00000000000000000000000000000000000000000000000000000000602083015251918291602083526020830190611893565b8280fd5b5050346102045781600319360112610204576020905160068152f35b50503461020457816003193601126102045760209051633b9aca008152f35b82843461027057602080600319360112610204576109b36118f1565b6109c16001600d5414611945565b600280600d556001600160a01b0391828116948581526003855286812080549460ff9586948593848316888110600014610d92575060ff19610a05931690556148ed565b975b82610a10611a34565b96610a5260809380858b01526000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b9790971660608b0152959097168c89018190526001600160701b039586168b8a01526001600160801b03978816895297818914610d8657610a9290614708565b958c82600185838b0151169b5b1494859283610d77575b505050610b79575b50505090839291610b6695940151169282511690878301511690866060818c86015116940151169360005260046020526001600160801b037dffffffffffffffffffffffffffff000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000060406000209760f81b169560f01b169360801b1691161717179055565b6001600d55818551941684521690820152f35b6007969192965488811690851c9781988a610bb98989880151167f0000000000000000000000000000000000000000000000000000000000000000611de6565b80915060a0880152829380610d6f575b610d5a575b50821603610d21575b50610be781600754871c946147b6565b978315610cb25750868c890151166d04ee2d6d415b85acef810000000090818102918183041490151715610c9e57610b669a9b9c9d9e9f508984939281610c328197610c6d95611a97565b16011692836001600160801b037fffffffffffffffffffffffffffffffff0000000000000000000000000000000091169160801b1617600755565b8c88015216855288606086019181835116908114610c96575b1690528a99989796958c80610ab1565b506001610c86565b8f836011602492634e487b7160e01b835252fd5b9190508b9c9d9e50889250610d1c8884610ce4610b669d9e9f8b610cdc9160085495015116614b23565b838a1c614b38565b91166001600160801b037fffffffffffffffffffffffffffffffff0000000000000000000000000000000091169160801b1617600855565b610c6d565b60801b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b038216176007558f610bd7565b610d679293501682614b38565b908a38610bce565b506001610bc9565b8a015116149050828b8f610aa9565b958c826001819b610a9f565b9250505097610a07565b8391503461020457602060031936011261020457610db86118f1565b90610dc2826123c0565b15610de55760208480856001600160a01b03861681526001845220549051908152f35b606490602085519162461bcd60e51b8352820152601e60248201527f4d6f6f6e3a2050616972206c6f636b65642e2043616c6c20736b696d282900006044820152fd5b505034610204578160031936011261020457602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b839150346102045760a060031936011261020457610e7f6118f1565b90610e8861190c565b906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163303610ede57509061053a91610ecd6001600d5414611945565b608435916064359160443591611eb1565b606490602086519162461bcd60e51b8352820152601960248201527f43616e206f6e6c792062652063616c6c65642062792053554e000000000000006044820152fd5b505034610204578160031936011261020457602090516d04ee2d6d415b85acef81000000008152f35b8284346102705760206003193601126102705750610f666118f1565b610f6e6119b3565b906101209082828101946001600160a01b039283811687527f0000000000000000000000000000000000000000000000000000000000000000610fb091611de6565b9190508380885116610fd69060005260056020526001600160a01b036040600020541690565b16835283875116610fe690611e26565b9396929590919488602085019c828601976060870195608088019760a001981515895260ff16875260ff1685528d6001600160701b03809b81809c168b52169052511661103290611e6b565b999198909a6101009a67ffffffffffffffff169d8e8c8201528c6101a08201528a61018082015251169d5116965116925160ff16935160ff16945115159581519c8d5260208d01528b015260608a0152608089015260a088015260c087015260e086015284015282015261014090f35b505034610204578160031936011261020457602090516702c68af0bb1400008152f35b5050346102045781600319360112610204576020905162ffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b90503461095857816003193601126109585761111f6118f1565b602435926111316001600d5414611945565b6002600d556001600160a01b039283831692308414159081611418575b5080611403575b806113d7575b806113ce575b1561138c575061117284303361397b565b61117a6119b3565b9061012082019280845261118d90611e26565b969297919490956020810198828201956060830197608084019960a085019b15158c5260ff168a5260ff1688526001600160701b039b8c8080941692838a52168c526111d891611a8a565b6111e190613f11565b1685528a918a8c858088511661120b9060005260056020526001600160a01b036040600020541690565b1680855280611259575b505050505015611229575b886001600d5580f35b8761124c9860ff9392849351169851169351169351169351169351151594612e73565b3880808080808080611220565b61126290613f2a565b509092909180611381575b80611376575b61127f575b9150611215565b8c5161132b9750158015919061136f5784835b16610140880152501561136857505b16610160830152670de0b6b3a76400008b87511610158061135c575b611347575b600854906001600160801b0390600754918151936112df856117dd565b818116855260801c602085015282169083015260801c606082015267ffffffffffffffff61130f85875116611e6b565b92909192166101008501526101a0840152610180830152613f8f565b61133c6106fe6106f9600193612fb8565b38808a81808e611278565b61135384865116611d9f565b600287526112c2565b5060ff875116156112bd565b90506112a1565b8484611292565b508382161515611273565b50838316151561126d565b6020606492519162461bcd60e51b8352820152601d60248201527f4d6f6f6e3a20696e76616c696420726179206f72203020616d6f756e740000006044820152fd5b50841515611161565b50837f00000000000000000000000000000000000000000000000000000000000000001683141561115b565b50828652600660205283828720541615611155565b90503b15153861114e565b505034610204578160031936011261020457602090600c549051908152f35b50503461020457816003193601126102045760085490516001600160801b038216815260809190911c6020820152604090f35b5050346102045781600319360112610204576020905160128152f35b8284346102705760206003193601126102705760806001600160701b0360ff80856114f36114bd6118f1565b6000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b94929690916001600160801b038551981688521660208701521690840152166060820152f35b5050346102045781600319360112610204576020905162ffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b838334610204576060600319360112610204576115746118f1565b61157c61190c565b6044359161158e6001600d5414611945565b6002600d556001600160a01b038116808652602095600287528581203382528752858120549760001989036115cc575b505050906108ad9291611ab7565b85891061162f5750846108ad96979882846115fa945260028b528981203382528b5289838303912055611990565b9086519182527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925883393a385949387806115be565b6064908888519162461bcd60e51b8352820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152fd5b505034610204578160031936011261020457602090600a549051908152f35b505034610204578160031936011261020457602091549051908152f35b505034610204578160031936011261020457602090516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b5050346102045780600319360112610204576020918161170f6118f1565b91602435918291338152600287526001600160a01b038282209516948582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b91905034610958578260031936011261095857610809925080519161178783611823565b82527f4d6f6f6e00000000000000000000000000000000000000000000000000000000602083015251918291602083526020830190611893565b8490346102045781600319360112610204578061dead60209252f35b6080810190811067ffffffffffffffff8211176117f957604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116117f957604052565b6040810190811067ffffffffffffffff8211176117f957604052565b6020810190811067ffffffffffffffff8211176117f957604052565b6060810190811067ffffffffffffffff8211176117f957604052565b60e0810190811067ffffffffffffffff8211176117f957604052565b919082519283825260005b8481106118dd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b60208183018101518483018201520161189e565b600435906001600160a01b038216820361190757565b600080fd5b602435906001600160a01b038216820361190757565b34611907576000600319360112611907576020604051670de0b6b3a76400008152f35b1561194c57565b606460405162461bcd60e51b815260206004820152600a60248201527f5265656e7472616e6379000000000000000000000000000000000000000000006044820152fd5b9190820391821161199d57565b634e487b7160e01b600052601160045260246000fd5b604051906101e0820182811067ffffffffffffffff8211176117f957604052816101c06000918281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a08201520152565b6040519060c0820182811067ffffffffffffffff8211176117f9576040528160a06000918281528260208201528260408201528260608201528260808201520152565b8181029291811591840414171561199d57565b9190820180921161199d57565b8115611aa1570490565b634e487b7160e01b600052601260045260246000fd5b916001600160a01b03918281168015611ca05783851660009181835260209360018552604097868986205410611c5d5761dead8314611c4b5790611afb9187613a42565b959015611c0057666a94d74f430000808202908282041482151715611bec576106fe979486856106f99995610120978d9a96611bea9e670de0b6b3a7640000611bab980496611b4a8884611990565b9284825260018852828220908154039055848152818120838154019055308152208681540190558b519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef948591a3885191838352853093a383613e37565b600854946001600160801b0360075492825197611bc7896117dd565b828116895260801c9088015282169086015260801c60608501520151169061343d565b565b602485634e487b7160e01b81526011600452fd5b828452600185528784208054829003905581845292879020805484019055955191825293507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9250a3565b9596505050505050611bea92506139e8565b6064868a519062461bcd60e51b82526004820152601b60248201527f45524332303a2042616c616e636520696e73756666696369656e7400000000006044820152fd5b606460405162461bcd60e51b815260206004820152601f60248201527f45524332303a207472616e7366657220746f207a65726f2061646472657373006044820152fd5b600954811015611d1b5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b634e487b7160e01b600052603260045260246000fd5b600b54811015611d1b57600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90190600090565b600a54811015611d1b57600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80190600090565b60095490680100000000000000008210156117f957611dc7826001611bea9401600955611ce4565b9091906001600160a01b038084549260031b9316831b921b1916179055565b6001600160a01b03611df99216906142a3565b8192919215611e1d5760200151906001600160701b03808311611e195750565b9150565b50600091508190565b611e3d906000526005602052600160406000200190565b546001600160701b0391828216928260701c169160ff8160e01c169160ff808360e81c169260f01c16151590565b611e82906000526005602052600260406000200190565b54906bffffffffffffffffffffffff611eae8360c01c91611ea48186166146b5565b9460601c166146b5565b91565b939293831580156123ab575b6123a45760ff6001600160701b0381611f486001600160a01b036001600160801b0395611bea9a82611eed611a34565b99611ef6611a34565b9b8260808d019516855260a08c01521660808b015260a08a015251166000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b959295939091931660608801521660408601521660208401521681526001600160701b036001600160801b0360ff611fbd6001600160a01b036080870151166000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b959293908160408a01971660608a015216855216602086015216835260ff60408301511615612390575b5160ff1615612380575b60075492600160ff60408401511614612365575b600160ff60408501511614612347575b836001600160801b0361217d94951683526001600160801b038116855260a083018281510381528260a08701510160a0870152600160ff6040860151161461230f575b50600160ff604087015116146122d5575b60ff6040840151169160ff6040870151169060018360801c92148080916122ca575b1561228d57506001600160801b03808092168301169116811061227f575b8160801c6001600160801b03821603612243575b50506001600160a01b03608083015116916001600160801b0381511660ff60606001600160701b03602085015116930151169360005260046020526001600160801b037dffffffffffffffffffffffffffff000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000060406000209760f81b169560f01b169360801b1691161717179055565b6001600160a01b03608082015116906001600160801b038151166001600160701b036020830151169060ff606081604086015116940151169360005260046020526001600160801b037dffffffffffffffffffffffffffff000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000060406000209760f81b169560f01b169360801b1691161717179055565b60801b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b03919091161760075538806120bd565b506001600160801b036120a9565b6001851490816122c1575b506122a4575b506120a9565b6122bb91506001600160801b03168260801c614b38565b3861229e565b90501538612298565b50600185141561208b565b6001600160a01b0360808601511660ff612307606088019282845116670de0b6b3a764000060a08b0151101591614830565b169052612069565b60ff61233e6001600160a01b036080870151166060870193670de0b6b3a7640000848651169151101591614830565b16905238612058565b61235e61217d936001600160801b038616906147b6565b9250612015565b9061237a906001600160801b038516906147b6565b90612005565b9061238a90614708565b90611ff1565b9061239c60ff91614708565b919050611fe7565b5050505050565b506001600160a01b0380831690821614611ebd565b6001600160a01b039081811691600092808452600660205260ff604085205460a01c16156125145760ff80936123f46119b3565b9383855283875260066020528060408820541693612419610120870195808752611e26565b9792939a9060a08b0198151589521660808a01521660608801526001600160701b039788809216604089015216602087015261245483613f2a565b50989195909515612505576124b89582610160925115159a8b6000146124f45761247f828216613f11565b9b5b826101408d019d168d526000146124e3575061249d9116613f11565b975b0196168652875260016020526040872054935116611de6565b9290156124d9576124cc93519051926148a6565b6124d35790565b50600190565b5050505050600190565b6124ee925016613f11565b9761249f565b6124ff828416613f11565b9b612481565b50505050505050505050600190565b50505050600190565b6040519061252a826117dd565b60006060838281528260208201528260408201520152565b8115611aa1570690565b3d156125b05767ffffffffffffffff903d8281116117f95760405192601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168401908111848210176117f95760405282523d6000602084013e565b606090565b926125be61251d565b506125c76119b3565b506001600160801b038060408601511681855116900316600160ff60408601511603612d83576001600160801b0360208601511615612d835780612d07575b50633b9aca006001600160701b0360208501511610612d025760006001600160a01b036101208401511615612cb2575b60005b633b9aca006001600160701b03602087015116101580612ca8575b15612c7f57600101633b9aca006001600160801b03875116108015612c8e575b612c7f576001600160a01b036101208501511615612995575b6126bd6001600160701b036020870151166001600160801b038851166001600160801b0360208a01511691614efc565b6101808501908151801560001461298757505060005b808015612977576001600160701b0360208801511680911161296f575b61273861270261273f92855190614d5c565b936001600160701b03612729858260208d015116600082821160001461292a575003613f11565b16908160208b01525190614d5c565b8093611990565b906001600160a01b03610120880151166001600160a01b0360808a015116604051927f7a98be9c0000000000000000000000000000000000000000000000000000000060208501526024928385015260448401526064908184015282528160a081011067ffffffffffffffff60a08401111761295b57506001600160801b03916000808360a061281b9501604052602081519101827f0000000000000000000000000000000000000000000000000000000000000000620249f0f161280261254c565b506128bb575b612815838b511691614b23565b90614b38565b168752633b9aca008110612830575b50612639565b6128ad906128426101c0870151614ba9565b6001600160801b03612863608088019260008452612815838c511691614b23565b1688526001600160a01b0361012087015116906001600160701b03602088015116906001600160701b0360408901511660ff8060608b0151169251169260a08a0151151594612e73565b60006101208501523861282a565b89838151168a811560001461293a576001600160701b03925061291f915060005b8360208293015116809111612932575b508c60208761290381838501511661281586614b23565b1691015260208c0151831660008282111561292a575003613f11565b1660208a0152612808565b915050613f11565b9050386128ec565b61295661291f928760206001600160701b039601511686614efc565b6128dc565b634e487b7160e01b60005260416004526000fd5b9050806126f0565b5050506000610120850152612639565b61299091614c43565b6126d3565b600a54918215612ba65780600d1b188060071c188060111b18916129b98184612542565b90816101c0870152811015611d1b576001600160701b0360ff81612a156001600160a01b038395600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8015416806101208b0152611e26565b97929395908c60a0602082019a15159101521660808c01521660608a015216604088015216815267ffffffffffffffff612a5c6001600160a01b0361012088015116611e6b565b92909192166101008801526101a0870152610180860152600260ff60808701511603612a88575061268d565b612a966101c0860151614ba9565b6001600160701b036001600160a01b03610120870151169151166040860151606087015191612ad960a08901511515946000526005602052600160406000200190565b9360009015612b6557507bffffffffffffffffffffffffffff00000000000000000000000000007cff0000000000000000000000000000000000000000000000000000000060015b60f01b9460e01b169260701b161717177fff000000000000000000000000000000000000000000000000000000000000008254161790556000610120850152612639565b7cff000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffff000000000000000000000000000091612b21565b50505091612c7b909391935b6001600160a01b03608082015116906001600160801b036040850151166001600160701b036020830151169060ff606081604086015116940151169360005260046020526001600160801b037dffffffffffffffffffffffffffff000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000060406000209760f81b169560f01b169360801b1691161717179055565b9190565b505091612c7b90939193612bb2565b50633b9aca006001600160801b0360208801511610612674565b5060068110612654565b5060808301516040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602082019244845260601b16604082015260348152612cfa8161185b565b519020612636565b915090565b612d52612d5791612d456001600160a01b036080880151167f0000000000000000000000000000000000000000000000000000000000000000611de6565b80915060a0880152611a77565b614b5b565b6020840190612d7a612d756001600160701b03928385511690611a8a565b613f11565b16905238612606565b50915090565b612da0906000526005602052600160406000200190565b9315612e28576001600160701b037bffffffffffffffffffffffffffff00000000000000000000000000007dff000000000000000000000000000000000000000000000000000000000060015b60f01b9560e81b169360701b1691161717177fff00000000000000000000000000000000000000000000000000000000000000825416179055565b6001600160701b037bffffffffffffffffffffffffffff00000000000000000000000000007dff00000000000000000000000000000000000000000000000000000000006000612ded565b612e8a906000526005602052600160406000200190565b9415612f36576001600160701b037bffffffffffffffffffffffffffff00000000000000000000000000007cff000000000000000000000000000000000000000000000000000000007dff000000000000000000000000000000000000000000000000000000000060015b60f01b9760e81b169560e01b169360701b169116171717177fff00000000000000000000000000000000000000000000000000000000000000825416179055565b6001600160701b037bffffffffffffffffffffffffffff00000000000000000000000000007cff000000000000000000000000000000000000000000000000000000007dff00000000000000000000000000000000000000000000000000000000006000612ef5565b6001600160701b03918216908216039190821161199d57565b612fc061251d565b506009541561317157612fd5600c5444611a8a565b90612fde6119b3565b906000805b600681106132b9575b50156132b3576001600160a01b0361300681845116613f2a565b5090911580156132a2575b8015613291575b61324d5760a0850151158015929061324657815b6001600160701b03938461014089019416845260001461323e5750925b8261016087019416845261305c86614f2b565b845190666a94d74f4300009182810292818404149015171561199d57670de0b6b3a76400009182900480821161323757505b604088015185169080821161323057505b81811061321257600080848a511660a08b0151151589518851906040519260208401947ff03fc31000000000000000000000000000000000000000000000000000000000865260248501526044840152866064840152608483015260a482015260a4815261310c81611877565b5190823062055730f161311d61254c565b50156131d1579761315d9291856131416131719b828060408e015116911690612f9f565b168060408b015210806131c0575b6131aa575b50865116613f2a565b5091929092613174575b5050505050613f8f565b90565b60a087015115801591906131a35784835b1690521561319c57505b1690523880808080613167565b905061318f565b8484613185565b6131b390614bf6565b6000606088015238613154565b50600260ff60608a0151161461314f565b50509193956131719593506131e69150614bf6565b610120820151169180602083015116906040830151169060a060ff608085015116930151151593612d89565b50505050505061322461317193614bf6565b60006060830152613f8f565b905061309f565b905061308e565b905092613049565b809161302c565b505061325d613171939294614bf6565b61012082015116906001600160701b0380602083015116906040830151169060a060ff608085015116930151151593612d89565b506001600160701b03811615613018565b506001600160701b03821615613011565b91505090565b939060095494851561343457600192838101811161199d5786846132dd9201612542565b956001600160a01b036132ef88611ce4565b90549060031b1c16908161012088015281156134215750613318670de0b6b3a764000091611e26565b151560a08b015260ff90811660808b015290811660608a01526001600160701b0391821660408a0181905292821660208a0152929091106133c4575050505067ffffffffffffffff6133776001600160a01b0361012086015116611e6b565b92909192166101008601526101a08501526101808401526001600160a01b036133bb816101208601511660005260056020526001600160a01b036040600020541690565b16835238612fec565b613407929394506133d488614bf6565b6001600160a01b0361012088015116918160208901511691604089015116906080890151169160a0890151151593612d89565b60095415613419576001905b01612fe3565b505091505090565b9050929091921461341957600190613413565b50505091505090565b9061344661251d565b506009541561361b5761345b600c5444611a8a565b916134646119b3565b916000906000905b60068210613490575b5050156132b3576001600160a01b0361300681845116613f2a565b60095495929186156136115760019384810180911161199d57876134b391612542565b966001600160a01b036134c589611ce4565b90549060031b1c1690816101208901526001600160a01b03841682146135fd57506134f8670de0b6b3a764000091611e26565b151560a08c015260ff90811660808c015290811660608b01526001600160701b0391821660408b0181905292821660208b0152929091106135a657505050505067ffffffffffffffff6135586001600160a01b0361012086015116611e6b565b92909192166101008601526101a08501526101808401526001600160a01b0361359c816101208601511660005260056020526001600160a01b036040600020541690565b1683523880613475565b6135ea92939495506135b789614bf6565b6001600160a01b0361012089015116918160208a0151169160408a0151169060808a0151169160a08a0151151593612d89565b60095415613434576001905b019061346c565b9050939091929314613434576001906135f6565b5050505091505090565b5090565b61362761251d565b505a91600c54916136366119b3565b9161363f611a34565b945b62035b6061364f5a83611990565b10156138a557600b5480156138425780861015613839575b851015611d1b57600b6000528560026001600160701b036001600160801b036136f26001600160a01b038a7f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90154168060808701526000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b60ff908116606089018190529116604088015293166020860152168352146138195750600b548060001981011161199d5762035b60918160001961364f930188036137cb575b50600019600b5401600b556001600160a01b036080890151166001600160801b0389511660208a01519060408b01519260005260046020527dffffffffffffffffffffffffffff000000000000000000000000000000007eff00000000000000000000000000000000000000000000000000000000000060406000209460f01b169260801b16171790555b915050613641565b6137db6000196138139201611d31565b90546001600160a01b036137ee8b611d31565b92909360031b1c16906001600160a01b038084549260031b9316831b921b1916179055565b38613738565b61382f61364f9160019662035b609498966125b5565b95909401956137c3565b60009550613667565b5050935091905b6001600160a01b036101208201511680613866575b5050600c5590565b61389e916001600160701b03806020830151169060408301511660ff6060840151169160a060ff608086015116940151151594612e73565b388061385e565b5093509190613849565b6007546001600160801b0360085491816040850151168282168103613942575b5050808351169181811683149081159161392e575b506138ee57505050565b6020611bea93015116906001600160801b037fffffffffffffffffffffffffffffffff0000000000000000000000000000000091169160801b1617600855565b905060801c816020850151161415386138e4565b6001600160801b03167fffffffffffffffffffffffffffffffff00000000000000000000000000000000919091161760075538806138cf565b91906001600160a01b03809116928315611907571690600082815260016020526040812080548381106109585760209284927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9560409303905586815220818154019055604051908152a3565b6001600160a01b031660009181835260016020526040832080548281106105e85791602091817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef94039055808554038555604051908152a3565b600093918490613a506119b3565b948315613e2f57613a60826148ed565b600260ff613a6d846148ed565b92161480918115613e21575b5015613e185715613e125781905b6001600160a01b03809216808852845260209260068452604080968482882054169260ff808c6060613ac061012098808a850152611e26565b979396919297151560a0870152166080850152169101528c6001600160701b03958680941691015216878c0152613af9868c5116613f2a565b50959115613d235790849392918d9560a087015115159788600014613e0157613b23828216613f11565b985b826101409a168a8a0152600014613df05750613b419116613f11565b935b61016080960194168452878d51168a52600189528c888c8c8c82822054988486511683526006825260ff8484205460a01c16613d34575b5050505080613b90938301511691511690611de6565b969015613d23578c51881691889182168303613cf8575050508101908110613cef575b915b808a0151158015613ce4575b613cd857808a0151613bd8838c01518583886148a6565b15908115613cce575b50613cc05790600592918a0193845190818111600014613cb157613c089150855190611990565b905b8a018051909281811115613ca257613c259150835190611990565b915b51029251029102600682028111918215613c95575b5050613c8b578551168252600690522080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b5060019550505050565b60021b1190503880613c3c565b613cab91611990565b91613c27565b613cba91611990565b90613c0a565b506001995050505050505050565b9050841438613be1565b50949850505050505050565b50818a015115613bc1565b50600019613bb3565b9593951614613d08575b50613bb5565b909281811115613d1b57035b9138613d02565b505085613d14565b5060019c5050505050505050505050565b51808a11613d78575b50845184168252600690522080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690558c8c8c38613b7a565b9350505050613d88915085611990565b666a94d74f43000090818102918183041490151715613ddc5788808f92938e8e60068f613dd1670de0b6b3a7640000613b909a04613dcb81898c5116309061397b565b89613e37565b929450509195613d3d565b60248b634e487b7160e01b81526011600452fd5b613dfb925016613f11565b93613b43565b613e0c828416613f11565b98613b25565b80613a87565b50919550505050565b6002915060ff161438613a79565b509094505050565b9061012082016001600160a01b039081815116827f00000000000000000000000000000000000000000000000000000000000000001614613f0457918391612d7593670de0b6b3a76400006040611bea970193613ea16001600160701b0397889283885116611a8a565b16808552101580613ef5575b613edd575b5116928060208401511691511660ff6060840151169160a060ff608086015116940151151594612e73565b613ee982825116611d9f565b60026060850152613eb2565b5060ff60608501511615613ead565b5050611bea9150306139e8565b6001600160701b039081811115613f26575090565b1690565b613f339061433a565b90918215613f825760208201519063ffffffff60606040850151940151926001600160701b038091818111600014613f7c57505b9481811115613f765750921690565b16921690565b16613f67565b6000925082915081908190565b919091613f9a61251d565b5060208301926001600160701b0390818551166140106140096140026001600160a01b03946101209987613ff4888d850151167f000000000000000000000000000000000000000000000000000000000000000090611de6565b9061428f575b5050506152c8565b9093614d5c565b8092615417565b6080829492019260ff8451169885019183835116633b9aca0082118b908080614284575b1561425b575060ff161561422d575b5060ff60025b16998a8652819a600281146000146141e057506002146141bd575b50600098905088811261416c5761407a90614b23565b6001600160801b039081808951168183820116908110614165575b1688526060880190828251166140dc575b505050613171959697505b51169280602084015116906040840151169060a060ff80606087015116945116940151151594612e73565b829060208a01828d818351169050818482011690811061415e575b16905216996d04ee2d6d415b85acef81000000009a8b81029b818d04149015171561414a575061413161317198999a838093511690611a97565b16906040890191818351160116905287969538806140a6565b80634e487b7160e01b602492526011600452fd5b50806140f7565b5080614095565b6001600160801b039081885116907f80000000000000000000000000000000000000000000000000000000000000008114613ddc57906128156141b5926131719a9b9c03614b23565b1687526140b1565b909198506000828203921281831281169183139015161761199d57963880614064565b613171999a9b506001919250149081614222575b50614200575b506140b1565b6142196001600160801b0391612815838b511691614b23565b168752386141fa565b6002915014386141f4565b600a5490680100000000000000008210156117f957611dc78260016142559401600a55611d68565b38614043565b909150158061427a575b614272575b60ff90614049565b50600161426a565b5060028b14614265565b5060028d1415614034565b61429890613f11565b169052388781613ffa565b60009190829160405160208101917f70a082310000000000000000000000000000000000000000000000000000000083526024820152602481526142e68161185b565b5191617530fa903d8261432e575b508115614316576040519061430882611823565b60208252602060008184013e565b60405191506143248261183f565b6000825260009190565b602011159150386142f4565b906040519160208301927f0902f1ac0000000000000000000000000000000000000000000000000000000084526004815261437481611823565b6000809151619c40958487fa923d91841580156143f3575b6143c8575b5050826143bc575b50811561431657604051906143ad826117dd565b6060825260606000602084013e565b60601115915038614399565b600093945083925090602091826040516143e181611823565b8181520191848352fa903d3880614391565b506060831061438c565b60405191602091828401937f0dfe16810000000000000000000000000000000000000000000000000000000085526004815261443881611823565b600080915161c350968488fa933d91851580156144c1575b614497575b50508361448c575b50821561447c576040519161447183611823565b80835260008184013e565b915050604051906143248261183f565b82111592503861445d565b6000939550839250908491826040516144af81611823565b8181520191848352fa913d3880614455565b50848310614450565b60405191602091828401937f9d76ea580000000000000000000000000000000000000000000000000000000085526004815261443881611823565b60405191602091828401937f0dfe16810000000000000000000000000000000000000000000000000000000085526004815261454081611823565b6000809151619c40968488fa933d91851580156144c1576144975750508361448c5750821561447c576040519161447183611823565b60405191602091828401937fd21220a70000000000000000000000000000000000000000000000000000000085526004815261454081611823565b60405160208101907efdd58e0000000000000000000000000000000000000000000000000000000082526001602482015260009283928284604481950152604481526145fc816117dd565b519161c350fa913d8361463f575b5082156146295760206040519261462084611823565b8184528184013e565b6040519250906146388361183f565b8083529190565b6020111592503861460a565b6000929183926040519060208201927fe6a439050000000000000000000000000000000000000000000000000000000084526024830152604482015260448152614694816117dd565b5191619c40fa903d8261432e57508115614316576040519061430882611823565b60ff8160581c169060a882116146d7576affffffffffffffffffffff16901b90565b602482604051907f19a773db0000000000000000000000000000000000000000000000000000000082526004820152fd5b614710611a34565b506001600160a01b038060808301511690813b156147aa578061473283615537565b8192919261479e575b50506147925761474a82615559565b81929192614786575b505061477b5761476290615574565b50614771576001604082015290565b6002604082015290565b506002604082015290565b16151590503880614753565b50506002604082015290565b1615159050813861473b565b50506001604082015290565b906147bf611a34565b5060a08201519081151580614819575b6147d857505090565b6147f691612d52916001600160801b03908186511690031690611a77565b6020820190614813612d756001600160701b039283855116611a8a565b16905290565b506001600160801b038084511690821614156147cf565b918080614898575b1561487b575060ff161561484d575b50600290565b600b5490680100000000000000008210156117f957611dc78260016148759401600b55611d31565b38614847565b909150158061488b576124d35790565b50600260ff8216146124cc565b50600260ff83161415614838565b92908084101593846148e2575b84156148c1575b5050505090565b1115925090826148d7575b5050388080806148ba565b1115905038806148cc565b8284101594506148b3565b6001600160a01b03808216600092818452600391602091838352604091828720805460ff811680614b165750833b15614aff57505061492b82615562565b929015614ae55761493b9061556b565b929015614ae5578681169030821490811580614ad9575b614abd578861496286869361558d565b90501603614aa257876149736119b3565b848152941690308203614a815750506101208301528660a08301525b61012082019486865116878451168952600686528489209081547fffffffffffffffffffffffff0000000000000000000000000000000000000000161790558188528452828720805460ff19166002179055858551166149ee90611e26565b50939092919587860197818701976060880195608089019760ff16885260ff1686526001600160701b0394858092168a521689528a8a51168c52600590528a20558088885116965116945116905160ff16915160ff169260a00151151593614a5595612e73565b511690807f7297cc7aec39e96d2f174bfe7e4634f1a7d24e10f7b528310726b603e93bd7b291a2600290565b909150614a8f575b5061498f565b610120830152600160a083015238614a89565b5050919594505083525220600160ff19825416179055600190565b505050919594505083525220600160ff19825416179055600190565b50308986161415614952565b50919594505083525220600160ff19825416179055600190565b60ff19166001908117909155979650505050505050565b9850505050505050505090565b6001600160801b039081811115613f26575090565b6001600160801b0391908282168382161115614b5357031690565b505050600090565b906d04ee2d6d415b85acef81000000008083049281840284810483148515171561199d57614b8891611990565b8060011b908082046002149015171561199d5711614ba257565b9060010190565b600a54906000199182810190811161199d57808203614bce575b5050600a5401600a55565b614bef916001600160a01b03614be66137ee93611d68565b93905492611d68565b3880614bc3565b600954906000199182810190811161199d57808203614c1b575b505060095401600955565b614c3c916001600160a01b03614c336137ee93611ce4565b93905492611ce4565b3880614c10565b6f4b3b4ca85a86c47a098a22400000000080821715614b53578215614d53578082029082158015614d41575b614d35578390600094614c83575050505090565b60001993848282098480821091030394858411908115614d2d575b50614caa575b506148ba565b8293949550098160000382168092049360018380600003040190848311900302920304176000916001811480614d24575b15614ced575b50503880808080614ca4565b9091506002808260030218808302820302808302820302808302820302808302820302808302820302809202900302023880614ce1565b92508192614cdb565b965038614c9e565b50613171929150611a97565b5080614d4d8484611a97565b14614c6f565b50505060001990565b81811715614e23578181029080158015614e11575b614df957600092600019908181840984808210910303926f4b3b4ca85a86c47a098a22400000000092848411908115614df1575b50614db3575b505050505090565b7f540e3428f2184ce6ed35cdbbf77a210b8e66502f8e41ca48b0d57d3d827fcdb995500990828211900360da1b910360261c17023880808080614dab565b965038614da5565b506f4b3b4ca85a86c47a098a22400000000091500490565b5082614e1d8284611a97565b14614d71565b5050600090565b6702c68af0bb1400009080821715614b53578215614d5357808202908083830414614d35578390600094614c83575050505090565b6702c68af0bb14000081811715614e2357818102908281830414614ef2576000926000199081818409848082109103039261271092848411908115614eea575b50614eac57505050505090565b7fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e9195500990828211900360fc1b910360041c17023880808080614dab565b965038614e9f565b5061271091500490565b9080821715614b53578215614d53578082029082158015614d4157614d35578390600094614c83575050505090565b906001600160701b0390816040840151169182156152bf576101608401519361014081015190851580156152b7575b6152ac579081614f9b6001600160a01b036101208996950151167f000000000000000000000000000000000000000000000000000000000000000090611de6565b9190508661500186614ffc62ffffff7f00000000000000000000000000000000000000000000000000000000000000001694610180614fec6000199e8f81670de0b6b3a7640000809a020101611a97565b9960208301511691015190614d5c565b6155e4565b9161500c8585614e2a565b95808401958487106152a4575b61503b908789109789896000146152945761503391611990565b965b84614efc565b9683670a688906bd8b0000840204880197881061528c575b6703782dace9d90000838102908104840361199d57612710615076910498614e5f565b90818901988910615284575b840193841061527c575b8301928310615274575b6150b39293810190811061526d575b6150ae9061570f565b6157ef565b81811061525e5750506000915b600093806150f857506150dc959697506150e7575b5050615902565b91808311611e195750565b6150f192506158b8565b38806150d5565b92918215988915615239575b7f3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8511158061520a575b996150dc98999a81615202575b50806151d8575b156151c957838002918560021b0292156000146151a7575081811061519b576151739161516e91611990565b615abc565b91818311615184575b505050615902565b615193935060011b91036158b8565b38808061517c565b50506151736000615abc565b909161517392818119106000146151bf575050615abc565b61516e9250611a8a565b509192506150e7575050615902565b507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff851115615142565b90503861513b565b5081158061512e5761522557818104600286901b111561512e565b602486634e487b7160e01b81526012600452fd5b9861524a5782890483111598615104565b602485634e487b7160e01b81526012600452fd5b61526791611990565b916150c0565b50896150a5565b8a9250615096565b8b935061508c565b8c9850615082565b8b9750615053565b9061529e91611990565b96615035565b8b9650615019565b505050915050600090565b508115614f5a565b50915050600090565b906152d16119b3565b5061018082019182519261014082018051151580615409575b15615403576101608301516f4b3b4ca85a86c47a098a2240000000009081810291818304149015171561199d5761532961532e91615333935190611a97565b615c51565b6146b5565b84811180156153fb575b6153c65761010083019067ffffffffffffffff80835116438114615386575092612c7b93826101a0870180518094525243168093526001600160a01b0361012086015116615ecf565b9250506101a0840192835182116153a0575b505050509190565b816153bd94526001600160a01b0361012086015116905190615ecf565b38808080615398565b80612c7b9252806101a084015267ffffffffffffffff43169081610100850152806001600160a01b0361012086015116615ecf565b50841561533d565b50509190565b5061016083015115156152ea565b90916154216119b3565b5061018082018051801561552d57602084016154486001600160701b039283835116614d5c565b95808711156155245761546283916131719697980361594d565b604088019082825116806154bb575b50809150615486575b50505116905190614d5c565b61549261549a9161599e565b855190615a7d565b82518216818111156154b257035b168152813861547a565b505060006154a8565b80821161551f5750805b306000908152600160205260409020548082116155175750915b836154f08183511682861690612f9f565b1690526154fd82306139e8565b8181111561550e57035b8038615471565b50506000615507565b9050916154df565b6154c5565b50505050909190565b5050915090600090565b615540906143fd565b8192919215611e1d57602001516001600160a01b031690565b615540906144ca565b61554090614505565b61554090614576565b61557d906145b1565b8192919215611e1d576020015190565b6001600160a01b0392916155c7919084169084167f000000000000000000000000000000000000000000000000000000000000000061464b565b81939193156155d857602001511690565b50509050600090600090565b6702c68af0bb1400009080821715614b53578215614d535780820281838204146156d857908391600094615619575050505090565b6000199182818609828082109103039485851180156156cf575b61563f575b50506148ba565b849596509391929309928381600003821680920495600183806000030401908483119003029203041760009360018114806156c6575b15615690575b50508214159015151601388080808080615638565b6002600382028118808302820302808302820302808302820302808302820302808302820302918202900302029250388061567b565b94508194615675565b96508396615633565b9290506156f091506156ea8184611a97565b92612542565b151580615703575b156131715760010190565b506000198114156156f8565b6703782dace9d900009081811715614e235781810291811580156157dd575b6157bb5760009260001992838382098280821091030392670de0b6b3a76400009184831180156157b2575b615767575b50505050505090565b7faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994959650098093828211900360ee1b910360121c170291821415901515160138808080808061575e565b96508596615759565b5050670de0b6b3a7640000808204910615158061570357156131715760010190565b50806157e98385611a97565b1461572e565b81811715614e235781810291811580156158a6575b61588a5760009260001992838382098280821091030392612710918483118015615881575b6158365750505050505090565b7fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e9194959650098093828211900360fc1b910360041c170291821415901515160138808080808061575e565b96508596615829565b5050612710808204910615158061570357156131715760010190565b50806158b28385611a97565b14615804565b670de0b6b3a764000080821715614b53578215614d5357808202821580156158f0575b6156d857908391600094615619575050505090565b50816158fc8483611a97565b146158db565b81811715614e235781810291811580156157dd576157bb5760009260001992838382098280821091030392670de0b6b3a76400009184831180156157b2576157675750505050505090565b6702c68af0bb14000081811715614e23578181029180828404146157bb5760009260001992838382098280821091030392670de0b6b3a76400009184831180156157b2576157675750505050505090565b670de0b6b3a76400009081811715614e23578181029181158015615a6b575b615a4957600092600019928383820982808210910303926702c68af0bb140000918483118015615a40575b6159f55750505050505090565b7f5ff7786fcb32f6f86690bf7c4dc899aa6468a3b109ac0347c75429d9e5c5200d94959650098093828211900360ee1b910360121c170291821415901515160138808080808061575e565b965085966159e8565b50506702c68af0bb140000808204910615158061570357156131715760010190565b5080615a778385611a97565b146159bd565b6f4b3b4ca85a86c47a098a22400000000080821715614b53578215614d5357808202821580156158f0576156d857908391600094615619575050505090565b908115615c4b57600082700100000000000000000000000000000000811015615c3d575b68010000000000000000811015615c28575b640100000000811015615c13575b62010000811015615bfe575b610100811015615be9575b6010811015615bd4575b6004811015615bbf575b60021115615b9d575b60018091811c1b906000905b60078210615b8557505080928115908282159182615b72575b5050615b63575050565b9091925061199d576000190190565b615b7c9250611a97565b82118238615b59565b82615b9282939487611a97565b01811c920190615b40565b6001810180911115615b3457634e487b7160e01b600052601160045260246000fd5b60021c906002810180911161199d5790615b2b565b60041c906004810180911161199d5790615b21565b60081c906008810180911161199d5790615b17565b60101c906010810180911161199d5790615b0c565b60201c906020810180911161199d5790615b00565b60401c906040810180911161199d5790615af2565b50508160801c608090615ae0565b60009150565b8015615ec957806000700100000000000000000000000000000000821015615ebc575b68010000000000000000831015615eb0575b640100000000831015615ea4575b62010000831015615e98575b610100831015615e8c575b6010831015615e80575b600260049384811015615e75575b1015615e6d575b600190818101808211615e42576058811115615e57577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa98201908111615e4257809484821c9484831b906000198201918211615e2d57167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa88401838111615e2d5785901b808211918215615e12575b5050615da7575b5050505060a88211615d91575b6affffffffffffffffffffff6bff000000000000000000000091169160581b161790565b5060a890506affffffffffffffffffffff615d6d565b909192809401936b0100000000000000000000008503615d60577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa9294919395501c9301809211615dfd57509038808080615d60565b601190634e487b7160e01b6000525260246000fd5b14905080615e22575b3880615d59565b508380861614615e1b565b601183634e487b7160e01b6000525260246000fd5b601185634e487b7160e01b6000525260246000fd5b5050506bffffffffffffffffffffffff91501690565b600101615cca565b91810191811c615cc3565b600492831c9201615cb5565b600892831c9201615cab565b601092831c9201615ca0565b602092831c9201615c94565b604092831c9201615c86565b50608081811c9250615c74565b50600090565b77ffffffffffffffffffffffff0000000000000000000000007fffffffffffffffff000000000000000000000000000000000000000000000000615f43615f3d615f376bffffffffffffffffffffffff95989796986000526005602052600260406000200190565b97615c51565b94615c51565b9460c01b169360601b1691161717905556fea2646970667358221220ce6437453674ef316bebdc9aca2ce719eb24bc6b69622a421c51115948b83c5264736f6c63430008180033000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000029ea7545def87022badc76323f373ea1e707c523000000000000000000000000000000000000000000000000000000000000001d0000000000000000000000000000674bc7700311b62845e2f5cdd4aff9990000000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff000000000000000000000000133ba2cdf20af0878bf0fcee6878caa5f506045b000000000000000000000000000000000000000000000000000000003b9aca00

Deployed ByteCode

0x608060408181526004918236101561001657600080fd5b600092833560e01c91826303fd2a45146117c15750816306fdde0314611763578163095ea7b3146116f157816317b5bb32146116ad57816318160ddd146116905781631d4cd5661461167157816323b872dd1461155957816324a9d853146115195781632ada259614611491578163313ce56714611475578163401ea9111461144257816343f45df714611423578163506c692d1461110557816353e1a7a0146110c55781635d9657f3146102b65781636189324b146110a2578163636c840314610f4a57816363a1089814610f2157816367ac46f314610e635781636ba980b914610e2857816370a0823114610d9c578163712bf4051461099757816384be07091461097857816394f2e4101461095c57816395d89b41146108fa57816399e37dff146108d8578163a479c94f146108b9578163a9059cbb14610870578163ba80105714610851578163c45a01551461080d578163cb8ae4da146107d6578163d73792a9146107b9578163dd62ed3e14610770578163e52253811461060a578163ebe10505146105ec578163f03fc310146102bb57508063fbaa4a2b146102b6578063fbfa77cf14610273578063fe33b3021461022a578063ff0ae962146102085763ff5f3820146101e857600080fd5b346102045781600319360112610204576020905162035b608152f35b5080fd5b5034610204578160031936011261020457602090516703782dace9d900008152f35b5090346102705760206003193601126102705760ff826001600160a01b0392836102526118f1565b168152600660205220548351928116835260a01c1615156020820152f35b80fd5b5034610204578160031936011261020457602090516001600160a01b037f000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff168152f35b611922565b839150346102045760a0600319360112610204576102d76118f1565b9260249182359283151584036105e857606435953033036105a6576001600160a01b0396610327888316928389526006602052868920805460ff8160a01c1661057b575b5050604435903061397b565b81875260016020528487205481808211156105705761036e91035b62ffffff7f00000000000000000000000000000000000000000000000000000000000026f31690611a77565b61037a60843582611a77565b916127109081810291818304149015171561055e579061039991611a8a565b8061054f57505085965b670a688906bd8b00009788810298818a04149015171561053d57670de0b6b3a764000087980495861561048c57156104905784516103e08161183f565b878152823b1561048c57879461045e869392849389519a8b98899788967f022c0d9f0000000000000000000000000000000000000000000000000000000088528701528501527f000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff166044840152608060648401526084830190611893565b03925af1908115610483575061047357505080f35b61047c9061180f565b6102705780f35b513d84823e3d90fd5b8780fd5b93949091928551906104a18261183f565b878252833b1561048c5761051d889692879389519a8b98899788967f022c0d9f0000000000000000000000000000000000000000000000000000000088528701528501527f000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff166044840152608060648401526084830190611893565b03925af19081156104835750610531575080f35b61053a9061180f565b80f35b8287601186634e487b7160e01b835252fd5b61055891611a97565b966103a3565b8489601188634e487b7160e01b835252fd5b505061036e87610342565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690558a8061031b565b506014906020606494519362461bcd60e51b85528401528201527f4d6f6f6e3a2073656c662d63616c6c206f6e6c790000000000000000000000006044820152fd5b8480fd5b50503461020457816003193601126102045760209051620557308152f35b5050346102045781600319360112610204576106fe6106f9610703926106346001600d5414611945565b6002600d55610641611a34565b9033608083015260ff610684336000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b841660608701529092168385019081526001600160701b0392831660208601526001600160801b039182168552600854600754855192969390916106c7846117dd565b818116845260801c602084015281168583015260801c6060820152600160ff829651161461070b575b50505050612fb8565b61361f565b6138af565b6001600d5580f35b6107209293945061071a6119b3565b906125b5565b9290926001600160a01b03610120820151169182156106f0578361076794602084015116918301511660ff6060840151169160a060ff608086015116940151151594612e73565b388080806106f0565b5050346102045780600319360112610204578060209261078e6118f1565b61079661190c565b6001600160a01b0391821683526002865283832091168252845220549051908152f35b505034610204578160031936011261020457602090516127108152f35b50503461020457816003193601126102045760075490516001600160801b038216815260809190911c6020820152604090f35b0390f35b505034610204578160031936011261020457602090516001600160a01b037f00000000000000000000000029ea7545def87022badc76323f373ea1e707c523168152f35b5050346102045781600319360112610204576020906009549051908152f35b5050346102045780600319360112610204576020906108ad6108906118f1565b61089e6001600d5414611945565b6002600d556024359033611ab7565b6001600d555160018152f35b505034610204578160031936011261020457602090600b549051908152f35b50503461020457816003193601126102045760209051666a94d74f4300008152f35b91905034610958578260031936011261095857610809925080519161091e83611823565b82527f4d4f4f4e00000000000000000000000000000000000000000000000000000000602083015251918291602083526020830190611893565b8280fd5b5050346102045781600319360112610204576020905160068152f35b50503461020457816003193601126102045760209051633b9aca008152f35b82843461027057602080600319360112610204576109b36118f1565b6109c16001600d5414611945565b600280600d556001600160a01b0391828116948581526003855286812080549460ff9586948593848316888110600014610d92575060ff19610a05931690556148ed565b975b82610a10611a34565b96610a5260809380858b01526000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b9790971660608b0152959097168c89018190526001600160701b039586168b8a01526001600160801b03978816895297818914610d8657610a9290614708565b958c82600185838b0151169b5b1494859283610d77575b505050610b79575b50505090839291610b6695940151169282511690878301511690866060818c86015116940151169360005260046020526001600160801b037dffffffffffffffffffffffffffff000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000060406000209760f81b169560f01b169360801b1691161717179055565b6001600d55818551941684521690820152f35b6007969192965488811690851c9781988a610bb98989880151167f0000000000000000000000000000674bc7700311b62845e2f5cdd4aff9990000611de6565b80915060a0880152829380610d6f575b610d5a575b50821603610d21575b50610be781600754871c946147b6565b978315610cb25750868c890151166d04ee2d6d415b85acef810000000090818102918183041490151715610c9e57610b669a9b9c9d9e9f508984939281610c328197610c6d95611a97565b16011692836001600160801b037fffffffffffffffffffffffffffffffff0000000000000000000000000000000091169160801b1617600755565b8c88015216855288606086019181835116908114610c96575b1690528a99989796958c80610ab1565b506001610c86565b8f836011602492634e487b7160e01b835252fd5b9190508b9c9d9e50889250610d1c8884610ce4610b669d9e9f8b610cdc9160085495015116614b23565b838a1c614b38565b91166001600160801b037fffffffffffffffffffffffffffffffff0000000000000000000000000000000091169160801b1617600855565b610c6d565b60801b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b038216176007558f610bd7565b610d679293501682614b38565b908a38610bce565b506001610bc9565b8a015116149050828b8f610aa9565b958c826001819b610a9f565b9250505097610a07565b8391503461020457602060031936011261020457610db86118f1565b90610dc2826123c0565b15610de55760208480856001600160a01b03861681526001845220549051908152f35b606490602085519162461bcd60e51b8352820152601e60248201527f4d6f6f6e3a2050616972206c6f636b65642e2043616c6c20736b696d282900006044820152fd5b505034610204578160031936011261020457602090517f0000000000000000000000000000000000000000033b2e3c9fd0803ce80000008152f35b839150346102045760a060031936011261020457610e7f6118f1565b90610e8861190c565b906001600160a01b037f0000000000000000000000000000674bc7700311b62845e2f5cdd4aff9990000163303610ede57509061053a91610ecd6001600d5414611945565b608435916064359160443591611eb1565b606490602086519162461bcd60e51b8352820152601960248201527f43616e206f6e6c792062652063616c6c65642062792053554e000000000000006044820152fd5b505034610204578160031936011261020457602090516d04ee2d6d415b85acef81000000008152f35b8284346102705760206003193601126102705750610f666118f1565b610f6e6119b3565b906101209082828101946001600160a01b039283811687527f000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff610fb091611de6565b9190508380885116610fd69060005260056020526001600160a01b036040600020541690565b16835283875116610fe690611e26565b9396929590919488602085019c828601976060870195608088019760a001981515895260ff16875260ff1685528d6001600160701b03809b81809c168b52169052511661103290611e6b565b999198909a6101009a67ffffffffffffffff169d8e8c8201528c6101a08201528a61018082015251169d5116965116925160ff16935160ff16945115159581519c8d5260208d01528b015260608a0152608089015260a088015260c087015260e086015284015282015261014090f35b505034610204578160031936011261020457602090516702c68af0bb1400008152f35b5050346102045781600319360112610204576020905162ffffff7f00000000000000000000000000000000000000000000000000000000000026f3168152f35b90503461095857816003193601126109585761111f6118f1565b602435926111316001600d5414611945565b6002600d556001600160a01b039283831692308414159081611418575b5080611403575b806113d7575b806113ce575b1561138c575061117284303361397b565b61117a6119b3565b9061012082019280845261118d90611e26565b969297919490956020810198828201956060830197608084019960a085019b15158c5260ff168a5260ff1688526001600160701b039b8c8080941692838a52168c526111d891611a8a565b6111e190613f11565b1685528a918a8c858088511661120b9060005260056020526001600160a01b036040600020541690565b1680855280611259575b505050505015611229575b886001600d5580f35b8761124c9860ff9392849351169851169351169351169351169351151594612e73565b3880808080808080611220565b61126290613f2a565b509092909180611381575b80611376575b61127f575b9150611215565b8c5161132b9750158015919061136f5784835b16610140880152501561136857505b16610160830152670de0b6b3a76400008b87511610158061135c575b611347575b600854906001600160801b0390600754918151936112df856117dd565b818116855260801c602085015282169083015260801c606082015267ffffffffffffffff61130f85875116611e6b565b92909192166101008501526101a0840152610180830152613f8f565b61133c6106fe6106f9600193612fb8565b38808a81808e611278565b61135384865116611d9f565b600287526112c2565b5060ff875116156112bd565b90506112a1565b8484611292565b508382161515611273565b50838316151561126d565b6020606492519162461bcd60e51b8352820152601d60248201527f4d6f6f6e3a20696e76616c696420726179206f72203020616d6f756e740000006044820152fd5b50841515611161565b50837f0000000000000000000000000000674bc7700311b62845e2f5cdd4aff99900001683141561115b565b50828652600660205283828720541615611155565b90503b15153861114e565b505034610204578160031936011261020457602090600c549051908152f35b50503461020457816003193601126102045760085490516001600160801b038216815260809190911c6020820152604090f35b5050346102045781600319360112610204576020905160128152f35b8284346102705760206003193601126102705760806001600160701b0360ff80856114f36114bd6118f1565b6000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b94929690916001600160801b038551981688521660208701521690840152166060820152f35b5050346102045781600319360112610204576020905162ffffff7f000000000000000000000000000000000000000000000000000000000000001d168152f35b838334610204576060600319360112610204576115746118f1565b61157c61190c565b6044359161158e6001600d5414611945565b6002600d556001600160a01b038116808652602095600287528581203382528752858120549760001989036115cc575b505050906108ad9291611ab7565b85891061162f5750846108ad96979882846115fa945260028b528981203382528b5289838303912055611990565b9086519182527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925883393a385949387806115be565b6064908888519162461bcd60e51b8352820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152fd5b505034610204578160031936011261020457602090600a549051908152f35b505034610204578160031936011261020457602091549051908152f35b505034610204578160031936011261020457602090516001600160a01b037f0000000000000000000000000000674bc7700311b62845e2f5cdd4aff9990000168152f35b5050346102045780600319360112610204576020918161170f6118f1565b91602435918291338152600287526001600160a01b038282209516948582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b91905034610958578260031936011261095857610809925080519161178783611823565b82527f4d6f6f6e00000000000000000000000000000000000000000000000000000000602083015251918291602083526020830190611893565b8490346102045781600319360112610204578061dead60209252f35b6080810190811067ffffffffffffffff8211176117f957604052565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff81116117f957604052565b6040810190811067ffffffffffffffff8211176117f957604052565b6020810190811067ffffffffffffffff8211176117f957604052565b6060810190811067ffffffffffffffff8211176117f957604052565b60e0810190811067ffffffffffffffff8211176117f957604052565b919082519283825260005b8481106118dd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b60208183018101518483018201520161189e565b600435906001600160a01b038216820361190757565b600080fd5b602435906001600160a01b038216820361190757565b34611907576000600319360112611907576020604051670de0b6b3a76400008152f35b1561194c57565b606460405162461bcd60e51b815260206004820152600a60248201527f5265656e7472616e6379000000000000000000000000000000000000000000006044820152fd5b9190820391821161199d57565b634e487b7160e01b600052601160045260246000fd5b604051906101e0820182811067ffffffffffffffff8211176117f957604052816101c06000918281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a08201520152565b6040519060c0820182811067ffffffffffffffff8211176117f9576040528160a06000918281528260208201528260408201528260608201528260808201520152565b8181029291811591840414171561199d57565b9190820180921161199d57565b8115611aa1570490565b634e487b7160e01b600052601260045260246000fd5b916001600160a01b03918281168015611ca05783851660009181835260209360018552604097868986205410611c5d5761dead8314611c4b5790611afb9187613a42565b959015611c0057666a94d74f430000808202908282041482151715611bec576106fe979486856106f99995610120978d9a96611bea9e670de0b6b3a7640000611bab980496611b4a8884611990565b9284825260018852828220908154039055848152818120838154019055308152208681540190558b519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef948591a3885191838352853093a383613e37565b600854946001600160801b0360075492825197611bc7896117dd565b828116895260801c9088015282169086015260801c60608501520151169061343d565b565b602485634e487b7160e01b81526011600452fd5b828452600185528784208054829003905581845292879020805484019055955191825293507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9250a3565b9596505050505050611bea92506139e8565b6064868a519062461bcd60e51b82526004820152601b60248201527f45524332303a2042616c616e636520696e73756666696369656e7400000000006044820152fd5b606460405162461bcd60e51b815260206004820152601f60248201527f45524332303a207472616e7366657220746f207a65726f2061646472657373006044820152fd5b600954811015611d1b5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b634e487b7160e01b600052603260045260246000fd5b600b54811015611d1b57600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90190600090565b600a54811015611d1b57600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80190600090565b60095490680100000000000000008210156117f957611dc7826001611bea9401600955611ce4565b9091906001600160a01b038084549260031b9316831b921b1916179055565b6001600160a01b03611df99216906142a3565b8192919215611e1d5760200151906001600160701b03808311611e195750565b9150565b50600091508190565b611e3d906000526005602052600160406000200190565b546001600160701b0391828216928260701c169160ff8160e01c169160ff808360e81c169260f01c16151590565b611e82906000526005602052600260406000200190565b54906bffffffffffffffffffffffff611eae8360c01c91611ea48186166146b5565b9460601c166146b5565b91565b939293831580156123ab575b6123a45760ff6001600160701b0381611f486001600160a01b036001600160801b0395611bea9a82611eed611a34565b99611ef6611a34565b9b8260808d019516855260a08c01521660808b015260a08a015251166000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b959295939091931660608801521660408601521660208401521681526001600160701b036001600160801b0360ff611fbd6001600160a01b036080870151166000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b959293908160408a01971660608a015216855216602086015216835260ff60408301511615612390575b5160ff1615612380575b60075492600160ff60408401511614612365575b600160ff60408501511614612347575b836001600160801b0361217d94951683526001600160801b038116855260a083018281510381528260a08701510160a0870152600160ff6040860151161461230f575b50600160ff604087015116146122d5575b60ff6040840151169160ff6040870151169060018360801c92148080916122ca575b1561228d57506001600160801b03808092168301169116811061227f575b8160801c6001600160801b03821603612243575b50506001600160a01b03608083015116916001600160801b0381511660ff60606001600160701b03602085015116930151169360005260046020526001600160801b037dffffffffffffffffffffffffffff000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000060406000209760f81b169560f01b169360801b1691161717179055565b6001600160a01b03608082015116906001600160801b038151166001600160701b036020830151169060ff606081604086015116940151169360005260046020526001600160801b037dffffffffffffffffffffffffffff000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000060406000209760f81b169560f01b169360801b1691161717179055565b60801b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001600160801b03919091161760075538806120bd565b506001600160801b036120a9565b6001851490816122c1575b506122a4575b506120a9565b6122bb91506001600160801b03168260801c614b38565b3861229e565b90501538612298565b50600185141561208b565b6001600160a01b0360808601511660ff612307606088019282845116670de0b6b3a764000060a08b0151101591614830565b169052612069565b60ff61233e6001600160a01b036080870151166060870193670de0b6b3a7640000848651169151101591614830565b16905238612058565b61235e61217d936001600160801b038616906147b6565b9250612015565b9061237a906001600160801b038516906147b6565b90612005565b9061238a90614708565b90611ff1565b9061239c60ff91614708565b919050611fe7565b5050505050565b506001600160a01b0380831690821614611ebd565b6001600160a01b039081811691600092808452600660205260ff604085205460a01c16156125145760ff80936123f46119b3565b9383855283875260066020528060408820541693612419610120870195808752611e26565b9792939a9060a08b0198151589521660808a01521660608801526001600160701b039788809216604089015216602087015261245483613f2a565b50989195909515612505576124b89582610160925115159a8b6000146124f45761247f828216613f11565b9b5b826101408d019d168d526000146124e3575061249d9116613f11565b975b0196168652875260016020526040872054935116611de6565b9290156124d9576124cc93519051926148a6565b6124d35790565b50600190565b5050505050600190565b6124ee925016613f11565b9761249f565b6124ff828416613f11565b9b612481565b50505050505050505050600190565b50505050600190565b6040519061252a826117dd565b60006060838281528260208201528260408201520152565b8115611aa1570690565b3d156125b05767ffffffffffffffff903d8281116117f95760405192601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168401908111848210176117f95760405282523d6000602084013e565b606090565b926125be61251d565b506125c76119b3565b506001600160801b038060408601511681855116900316600160ff60408601511603612d83576001600160801b0360208601511615612d835780612d07575b50633b9aca006001600160701b0360208501511610612d025760006001600160a01b036101208401511615612cb2575b60005b633b9aca006001600160701b03602087015116101580612ca8575b15612c7f57600101633b9aca006001600160801b03875116108015612c8e575b612c7f576001600160a01b036101208501511615612995575b6126bd6001600160701b036020870151166001600160801b038851166001600160801b0360208a01511691614efc565b6101808501908151801560001461298757505060005b808015612977576001600160701b0360208801511680911161296f575b61273861270261273f92855190614d5c565b936001600160701b03612729858260208d015116600082821160001461292a575003613f11565b16908160208b01525190614d5c565b8093611990565b906001600160a01b03610120880151166001600160a01b0360808a015116604051927f7a98be9c0000000000000000000000000000000000000000000000000000000060208501526024928385015260448401526064908184015282528160a081011067ffffffffffffffff60a08401111761295b57506001600160801b03916000808360a061281b9501604052602081519101827f000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff620249f0f161280261254c565b506128bb575b612815838b511691614b23565b90614b38565b168752633b9aca008110612830575b50612639565b6128ad906128426101c0870151614ba9565b6001600160801b03612863608088019260008452612815838c511691614b23565b1688526001600160a01b0361012087015116906001600160701b03602088015116906001600160701b0360408901511660ff8060608b0151169251169260a08a0151151594612e73565b60006101208501523861282a565b89838151168a811560001461293a576001600160701b03925061291f915060005b8360208293015116809111612932575b508c60208761290381838501511661281586614b23565b1691015260208c0151831660008282111561292a575003613f11565b1660208a0152612808565b915050613f11565b9050386128ec565b61295661291f928760206001600160701b039601511686614efc565b6128dc565b634e487b7160e01b60005260416004526000fd5b9050806126f0565b5050506000610120850152612639565b61299091614c43565b6126d3565b600a54918215612ba65780600d1b188060071c188060111b18916129b98184612542565b90816101c0870152811015611d1b576001600160701b0360ff81612a156001600160a01b038395600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8015416806101208b0152611e26565b97929395908c60a0602082019a15159101521660808c01521660608a015216604088015216815267ffffffffffffffff612a5c6001600160a01b0361012088015116611e6b565b92909192166101008801526101a0870152610180860152600260ff60808701511603612a88575061268d565b612a966101c0860151614ba9565b6001600160701b036001600160a01b03610120870151169151166040860151606087015191612ad960a08901511515946000526005602052600160406000200190565b9360009015612b6557507bffffffffffffffffffffffffffff00000000000000000000000000007cff0000000000000000000000000000000000000000000000000000000060015b60f01b9460e01b169260701b161717177fff000000000000000000000000000000000000000000000000000000000000008254161790556000610120850152612639565b7cff000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffff000000000000000000000000000091612b21565b50505091612c7b909391935b6001600160a01b03608082015116906001600160801b036040850151166001600160701b036020830151169060ff606081604086015116940151169360005260046020526001600160801b037dffffffffffffffffffffffffffff000000000000000000000000000000007eff0000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000060406000209760f81b169560f01b169360801b1691161717179055565b9190565b505091612c7b90939193612bb2565b50633b9aca006001600160801b0360208801511610612674565b5060068110612654565b5060808301516040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602082019244845260601b16604082015260348152612cfa8161185b565b519020612636565b915090565b612d52612d5791612d456001600160a01b036080880151167f0000000000000000000000000000674bc7700311b62845e2f5cdd4aff9990000611de6565b80915060a0880152611a77565b614b5b565b6020840190612d7a612d756001600160701b03928385511690611a8a565b613f11565b16905238612606565b50915090565b612da0906000526005602052600160406000200190565b9315612e28576001600160701b037bffffffffffffffffffffffffffff00000000000000000000000000007dff000000000000000000000000000000000000000000000000000000000060015b60f01b9560e81b169360701b1691161717177fff00000000000000000000000000000000000000000000000000000000000000825416179055565b6001600160701b037bffffffffffffffffffffffffffff00000000000000000000000000007dff00000000000000000000000000000000000000000000000000000000006000612ded565b612e8a906000526005602052600160406000200190565b9415612f36576001600160701b037bffffffffffffffffffffffffffff00000000000000000000000000007cff000000000000000000000000000000000000000000000000000000007dff000000000000000000000000000000000000000000000000000000000060015b60f01b9760e81b169560e01b169360701b169116171717177fff00000000000000000000000000000000000000000000000000000000000000825416179055565b6001600160701b037bffffffffffffffffffffffffffff00000000000000000000000000007cff000000000000000000000000000000000000000000000000000000007dff00000000000000000000000000000000000000000000000000000000006000612ef5565b6001600160701b03918216908216039190821161199d57565b612fc061251d565b506009541561317157612fd5600c5444611a8a565b90612fde6119b3565b906000805b600681106132b9575b50156132b3576001600160a01b0361300681845116613f2a565b5090911580156132a2575b8015613291575b61324d5760a0850151158015929061324657815b6001600160701b03938461014089019416845260001461323e5750925b8261016087019416845261305c86614f2b565b845190666a94d74f4300009182810292818404149015171561199d57670de0b6b3a76400009182900480821161323757505b604088015185169080821161323057505b81811061321257600080848a511660a08b0151151589518851906040519260208401947ff03fc31000000000000000000000000000000000000000000000000000000000865260248501526044840152866064840152608483015260a482015260a4815261310c81611877565b5190823062055730f161311d61254c565b50156131d1579761315d9291856131416131719b828060408e015116911690612f9f565b168060408b015210806131c0575b6131aa575b50865116613f2a565b5091929092613174575b5050505050613f8f565b90565b60a087015115801591906131a35784835b1690521561319c57505b1690523880808080613167565b905061318f565b8484613185565b6131b390614bf6565b6000606088015238613154565b50600260ff60608a0151161461314f565b50509193956131719593506131e69150614bf6565b610120820151169180602083015116906040830151169060a060ff608085015116930151151593612d89565b50505050505061322461317193614bf6565b60006060830152613f8f565b905061309f565b905061308e565b905092613049565b809161302c565b505061325d613171939294614bf6565b61012082015116906001600160701b0380602083015116906040830151169060a060ff608085015116930151151593612d89565b506001600160701b03811615613018565b506001600160701b03821615613011565b91505090565b939060095494851561343457600192838101811161199d5786846132dd9201612542565b956001600160a01b036132ef88611ce4565b90549060031b1c16908161012088015281156134215750613318670de0b6b3a764000091611e26565b151560a08b015260ff90811660808b015290811660608a01526001600160701b0391821660408a0181905292821660208a0152929091106133c4575050505067ffffffffffffffff6133776001600160a01b0361012086015116611e6b565b92909192166101008601526101a08501526101808401526001600160a01b036133bb816101208601511660005260056020526001600160a01b036040600020541690565b16835238612fec565b613407929394506133d488614bf6565b6001600160a01b0361012088015116918160208901511691604089015116906080890151169160a0890151151593612d89565b60095415613419576001905b01612fe3565b505091505090565b9050929091921461341957600190613413565b50505091505090565b9061344661251d565b506009541561361b5761345b600c5444611a8a565b916134646119b3565b916000906000905b60068210613490575b5050156132b3576001600160a01b0361300681845116613f2a565b60095495929186156136115760019384810180911161199d57876134b391612542565b966001600160a01b036134c589611ce4565b90549060031b1c1690816101208901526001600160a01b03841682146135fd57506134f8670de0b6b3a764000091611e26565b151560a08c015260ff90811660808c015290811660608b01526001600160701b0391821660408b0181905292821660208b0152929091106135a657505050505067ffffffffffffffff6135586001600160a01b0361012086015116611e6b565b92909192166101008601526101a08501526101808401526001600160a01b0361359c816101208601511660005260056020526001600160a01b036040600020541690565b1683523880613475565b6135ea92939495506135b789614bf6565b6001600160a01b0361012089015116918160208a0151169160408a0151169060808a0151169160a08a0151151593612d89565b60095415613434576001905b019061346c565b9050939091929314613434576001906135f6565b5050505091505090565b5090565b61362761251d565b505a91600c54916136366119b3565b9161363f611a34565b945b62035b6061364f5a83611990565b10156138a557600b5480156138425780861015613839575b851015611d1b57600b6000528560026001600160701b036001600160801b036136f26001600160a01b038a7f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90154168060808701526000526004602052604060002054906001600160801b038216916001600160701b038160801c169160ff8260f01c169160f81c90565b60ff908116606089018190529116604088015293166020860152168352146138195750600b548060001981011161199d5762035b60918160001961364f930188036137cb575b50600019600b5401600b556001600160a01b036080890151166001600160801b0389511660208a01519060408b01519260005260046020527dffffffffffffffffffffffffffff000000000000000000000000000000007eff00000000000000000000000000000000000000000000000000000000000060406000209460f01b169260801b16171790555b915050613641565b6137db6000196138139201611d31565b90546001600160a01b036137ee8b611d31565b92909360031b1c16906001600160a01b038084549260031b9316831b921b1916179055565b38613738565b61382f61364f9160019662035b609498966125b5565b95909401956137c3565b60009550613667565b5050935091905b6001600160a01b036101208201511680613866575b5050600c5590565b61389e916001600160701b03806020830151169060408301511660ff6060840151169160a060ff608086015116940151151594612e73565b388061385e565b5093509190613849565b6007546001600160801b0360085491816040850151168282168103613942575b5050808351169181811683149081159161392e575b506138ee57505050565b6020611bea93015116906001600160801b037fffffffffffffffffffffffffffffffff0000000000000000000000000000000091169160801b1617600855565b905060801c816020850151161415386138e4565b6001600160801b03167fffffffffffffffffffffffffffffffff00000000000000000000000000000000919091161760075538806138cf565b91906001600160a01b03809116928315611907571690600082815260016020526040812080548381106109585760209284927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9560409303905586815220818154019055604051908152a3565b6001600160a01b031660009181835260016020526040832080548281106105e85791602091817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef94039055808554038555604051908152a3565b600093918490613a506119b3565b948315613e2f57613a60826148ed565b600260ff613a6d846148ed565b92161480918115613e21575b5015613e185715613e125781905b6001600160a01b03809216808852845260209260068452604080968482882054169260ff808c6060613ac061012098808a850152611e26565b979396919297151560a0870152166080850152169101528c6001600160701b03958680941691015216878c0152613af9868c5116613f2a565b50959115613d235790849392918d9560a087015115159788600014613e0157613b23828216613f11565b985b826101409a168a8a0152600014613df05750613b419116613f11565b935b61016080960194168452878d51168a52600189528c888c8c8c82822054988486511683526006825260ff8484205460a01c16613d34575b5050505080613b90938301511691511690611de6565b969015613d23578c51881691889182168303613cf8575050508101908110613cef575b915b808a0151158015613ce4575b613cd857808a0151613bd8838c01518583886148a6565b15908115613cce575b50613cc05790600592918a0193845190818111600014613cb157613c089150855190611990565b905b8a018051909281811115613ca257613c259150835190611990565b915b51029251029102600682028111918215613c95575b5050613c8b578551168252600690522080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b5060019550505050565b60021b1190503880613c3c565b613cab91611990565b91613c27565b613cba91611990565b90613c0a565b506001995050505050505050565b9050841438613be1565b50949850505050505050565b50818a015115613bc1565b50600019613bb3565b9593951614613d08575b50613bb5565b909281811115613d1b57035b9138613d02565b505085613d14565b5060019c5050505050505050505050565b51808a11613d78575b50845184168252600690522080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690558c8c8c38613b7a565b9350505050613d88915085611990565b666a94d74f43000090818102918183041490151715613ddc5788808f92938e8e60068f613dd1670de0b6b3a7640000613b909a04613dcb81898c5116309061397b565b89613e37565b929450509195613d3d565b60248b634e487b7160e01b81526011600452fd5b613dfb925016613f11565b93613b43565b613e0c828416613f11565b98613b25565b80613a87565b50919550505050565b6002915060ff161438613a79565b509094505050565b9061012082016001600160a01b039081815116827f0000000000000000000000000000674bc7700311b62845e2f5cdd4aff99900001614613f0457918391612d7593670de0b6b3a76400006040611bea970193613ea16001600160701b0397889283885116611a8a565b16808552101580613ef5575b613edd575b5116928060208401511691511660ff6060840151169160a060ff608086015116940151151594612e73565b613ee982825116611d9f565b60026060850152613eb2565b5060ff60608501511615613ead565b5050611bea9150306139e8565b6001600160701b039081811115613f26575090565b1690565b613f339061433a565b90918215613f825760208201519063ffffffff60606040850151940151926001600160701b038091818111600014613f7c57505b9481811115613f765750921690565b16921690565b16613f67565b6000925082915081908190565b919091613f9a61251d565b5060208301926001600160701b0390818551166140106140096140026001600160a01b03946101209987613ff4888d850151167f000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff90611de6565b9061428f575b5050506152c8565b9093614d5c565b8092615417565b6080829492019260ff8451169885019183835116633b9aca0082118b908080614284575b1561425b575060ff161561422d575b5060ff60025b16998a8652819a600281146000146141e057506002146141bd575b50600098905088811261416c5761407a90614b23565b6001600160801b039081808951168183820116908110614165575b1688526060880190828251166140dc575b505050613171959697505b51169280602084015116906040840151169060a060ff80606087015116945116940151151594612e73565b829060208a01828d818351169050818482011690811061415e575b16905216996d04ee2d6d415b85acef81000000009a8b81029b818d04149015171561414a575061413161317198999a838093511690611a97565b16906040890191818351160116905287969538806140a6565b80634e487b7160e01b602492526011600452fd5b50806140f7565b5080614095565b6001600160801b039081885116907f80000000000000000000000000000000000000000000000000000000000000008114613ddc57906128156141b5926131719a9b9c03614b23565b1687526140b1565b909198506000828203921281831281169183139015161761199d57963880614064565b613171999a9b506001919250149081614222575b50614200575b506140b1565b6142196001600160801b0391612815838b511691614b23565b168752386141fa565b6002915014386141f4565b600a5490680100000000000000008210156117f957611dc78260016142559401600a55611d68565b38614043565b909150158061427a575b614272575b60ff90614049565b50600161426a565b5060028b14614265565b5060028d1415614034565b61429890613f11565b169052388781613ffa565b60009190829160405160208101917f70a082310000000000000000000000000000000000000000000000000000000083526024820152602481526142e68161185b565b5191617530fa903d8261432e575b508115614316576040519061430882611823565b60208252602060008184013e565b60405191506143248261183f565b6000825260009190565b602011159150386142f4565b906040519160208301927f0902f1ac0000000000000000000000000000000000000000000000000000000084526004815261437481611823565b6000809151619c40958487fa923d91841580156143f3575b6143c8575b5050826143bc575b50811561431657604051906143ad826117dd565b6060825260606000602084013e565b60601115915038614399565b600093945083925090602091826040516143e181611823565b8181520191848352fa903d3880614391565b506060831061438c565b60405191602091828401937f0dfe16810000000000000000000000000000000000000000000000000000000085526004815261443881611823565b600080915161c350968488fa933d91851580156144c1575b614497575b50508361448c575b50821561447c576040519161447183611823565b80835260008184013e565b915050604051906143248261183f565b82111592503861445d565b6000939550839250908491826040516144af81611823565b8181520191848352fa913d3880614455565b50848310614450565b60405191602091828401937f9d76ea580000000000000000000000000000000000000000000000000000000085526004815261443881611823565b60405191602091828401937f0dfe16810000000000000000000000000000000000000000000000000000000085526004815261454081611823565b6000809151619c40968488fa933d91851580156144c1576144975750508361448c5750821561447c576040519161447183611823565b60405191602091828401937fd21220a70000000000000000000000000000000000000000000000000000000085526004815261454081611823565b60405160208101907efdd58e0000000000000000000000000000000000000000000000000000000082526001602482015260009283928284604481950152604481526145fc816117dd565b519161c350fa913d8361463f575b5082156146295760206040519261462084611823565b8184528184013e565b6040519250906146388361183f565b8083529190565b6020111592503861460a565b6000929183926040519060208201927fe6a439050000000000000000000000000000000000000000000000000000000084526024830152604482015260448152614694816117dd565b5191619c40fa903d8261432e57508115614316576040519061430882611823565b60ff8160581c169060a882116146d7576affffffffffffffffffffff16901b90565b602482604051907f19a773db0000000000000000000000000000000000000000000000000000000082526004820152fd5b614710611a34565b506001600160a01b038060808301511690813b156147aa578061473283615537565b8192919261479e575b50506147925761474a82615559565b81929192614786575b505061477b5761476290615574565b50614771576001604082015290565b6002604082015290565b506002604082015290565b16151590503880614753565b50506002604082015290565b1615159050813861473b565b50506001604082015290565b906147bf611a34565b5060a08201519081151580614819575b6147d857505090565b6147f691612d52916001600160801b03908186511690031690611a77565b6020820190614813612d756001600160701b039283855116611a8a565b16905290565b506001600160801b038084511690821614156147cf565b918080614898575b1561487b575060ff161561484d575b50600290565b600b5490680100000000000000008210156117f957611dc78260016148759401600b55611d31565b38614847565b909150158061488b576124d35790565b50600260ff8216146124cc565b50600260ff83161415614838565b92908084101593846148e2575b84156148c1575b5050505090565b1115925090826148d7575b5050388080806148ba565b1115905038806148cc565b8284101594506148b3565b6001600160a01b03808216600092818452600391602091838352604091828720805460ff811680614b165750833b15614aff57505061492b82615562565b929015614ae55761493b9061556b565b929015614ae5578681169030821490811580614ad9575b614abd578861496286869361558d565b90501603614aa257876149736119b3565b848152941690308203614a815750506101208301528660a08301525b61012082019486865116878451168952600686528489209081547fffffffffffffffffffffffff0000000000000000000000000000000000000000161790558188528452828720805460ff19166002179055858551166149ee90611e26565b50939092919587860197818701976060880195608089019760ff16885260ff1686526001600160701b0394858092168a521689528a8a51168c52600590528a20558088885116965116945116905160ff16915160ff169260a00151151593614a5595612e73565b511690807f7297cc7aec39e96d2f174bfe7e4634f1a7d24e10f7b528310726b603e93bd7b291a2600290565b909150614a8f575b5061498f565b610120830152600160a083015238614a89565b5050919594505083525220600160ff19825416179055600190565b505050919594505083525220600160ff19825416179055600190565b50308986161415614952565b50919594505083525220600160ff19825416179055600190565b60ff19166001908117909155979650505050505050565b9850505050505050505090565b6001600160801b039081811115613f26575090565b6001600160801b0391908282168382161115614b5357031690565b505050600090565b906d04ee2d6d415b85acef81000000008083049281840284810483148515171561199d57614b8891611990565b8060011b908082046002149015171561199d5711614ba257565b9060010190565b600a54906000199182810190811161199d57808203614bce575b5050600a5401600a55565b614bef916001600160a01b03614be66137ee93611d68565b93905492611d68565b3880614bc3565b600954906000199182810190811161199d57808203614c1b575b505060095401600955565b614c3c916001600160a01b03614c336137ee93611ce4565b93905492611ce4565b3880614c10565b6f4b3b4ca85a86c47a098a22400000000080821715614b53578215614d53578082029082158015614d41575b614d35578390600094614c83575050505090565b60001993848282098480821091030394858411908115614d2d575b50614caa575b506148ba565b8293949550098160000382168092049360018380600003040190848311900302920304176000916001811480614d24575b15614ced575b50503880808080614ca4565b9091506002808260030218808302820302808302820302808302820302808302820302808302820302809202900302023880614ce1565b92508192614cdb565b965038614c9e565b50613171929150611a97565b5080614d4d8484611a97565b14614c6f565b50505060001990565b81811715614e23578181029080158015614e11575b614df957600092600019908181840984808210910303926f4b3b4ca85a86c47a098a22400000000092848411908115614df1575b50614db3575b505050505090565b7f540e3428f2184ce6ed35cdbbf77a210b8e66502f8e41ca48b0d57d3d827fcdb995500990828211900360da1b910360261c17023880808080614dab565b965038614da5565b506f4b3b4ca85a86c47a098a22400000000091500490565b5082614e1d8284611a97565b14614d71565b5050600090565b6702c68af0bb1400009080821715614b53578215614d5357808202908083830414614d35578390600094614c83575050505090565b6702c68af0bb14000081811715614e2357818102908281830414614ef2576000926000199081818409848082109103039261271092848411908115614eea575b50614eac57505050505090565b7fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e9195500990828211900360fc1b910360041c17023880808080614dab565b965038614e9f565b5061271091500490565b9080821715614b53578215614d53578082029082158015614d4157614d35578390600094614c83575050505090565b906001600160701b0390816040840151169182156152bf576101608401519361014081015190851580156152b7575b6152ac579081614f9b6001600160a01b036101208996950151167f000000000000000000000000ffff33ad6ab86cfe721ddfe97eac10958240ffff90611de6565b9190508661500186614ffc62ffffff7f00000000000000000000000000000000000000000000000000000000000026f31694610180614fec6000199e8f81670de0b6b3a7640000809a020101611a97565b9960208301511691015190614d5c565b6155e4565b9161500c8585614e2a565b95808401958487106152a4575b61503b908789109789896000146152945761503391611990565b965b84614efc565b9683670a688906bd8b0000840204880197881061528c575b6703782dace9d90000838102908104840361199d57612710615076910498614e5f565b90818901988910615284575b840193841061527c575b8301928310615274575b6150b39293810190811061526d575b6150ae9061570f565b6157ef565b81811061525e5750506000915b600093806150f857506150dc959697506150e7575b5050615902565b91808311611e195750565b6150f192506158b8565b38806150d5565b92918215988915615239575b7f3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8511158061520a575b996150dc98999a81615202575b50806151d8575b156151c957838002918560021b0292156000146151a7575081811061519b576151739161516e91611990565b615abc565b91818311615184575b505050615902565b615193935060011b91036158b8565b38808061517c565b50506151736000615abc565b909161517392818119106000146151bf575050615abc565b61516e9250611a8a565b509192506150e7575050615902565b507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff851115615142565b90503861513b565b5081158061512e5761522557818104600286901b111561512e565b602486634e487b7160e01b81526012600452fd5b9861524a5782890483111598615104565b602485634e487b7160e01b81526012600452fd5b61526791611990565b916150c0565b50896150a5565b8a9250615096565b8b935061508c565b8c9850615082565b8b9750615053565b9061529e91611990565b96615035565b8b9650615019565b505050915050600090565b508115614f5a565b50915050600090565b906152d16119b3565b5061018082019182519261014082018051151580615409575b15615403576101608301516f4b3b4ca85a86c47a098a2240000000009081810291818304149015171561199d5761532961532e91615333935190611a97565b615c51565b6146b5565b84811180156153fb575b6153c65761010083019067ffffffffffffffff80835116438114615386575092612c7b93826101a0870180518094525243168093526001600160a01b0361012086015116615ecf565b9250506101a0840192835182116153a0575b505050509190565b816153bd94526001600160a01b0361012086015116905190615ecf565b38808080615398565b80612c7b9252806101a084015267ffffffffffffffff43169081610100850152806001600160a01b0361012086015116615ecf565b50841561533d565b50509190565b5061016083015115156152ea565b90916154216119b3565b5061018082018051801561552d57602084016154486001600160701b039283835116614d5c565b95808711156155245761546283916131719697980361594d565b604088019082825116806154bb575b50809150615486575b50505116905190614d5c565b61549261549a9161599e565b855190615a7d565b82518216818111156154b257035b168152813861547a565b505060006154a8565b80821161551f5750805b306000908152600160205260409020548082116155175750915b836154f08183511682861690612f9f565b1690526154fd82306139e8565b8181111561550e57035b8038615471565b50506000615507565b9050916154df565b6154c5565b50505050909190565b5050915090600090565b615540906143fd565b8192919215611e1d57602001516001600160a01b031690565b615540906144ca565b61554090614505565b61554090614576565b61557d906145b1565b8192919215611e1d576020015190565b6001600160a01b0392916155c7919084169084167f00000000000000000000000029ea7545def87022badc76323f373ea1e707c52361464b565b81939193156155d857602001511690565b50509050600090600090565b6702c68af0bb1400009080821715614b53578215614d535780820281838204146156d857908391600094615619575050505090565b6000199182818609828082109103039485851180156156cf575b61563f575b50506148ba565b849596509391929309928381600003821680920495600183806000030401908483119003029203041760009360018114806156c6575b15615690575b50508214159015151601388080808080615638565b6002600382028118808302820302808302820302808302820302808302820302808302820302918202900302029250388061567b565b94508194615675565b96508396615633565b9290506156f091506156ea8184611a97565b92612542565b151580615703575b156131715760010190565b506000198114156156f8565b6703782dace9d900009081811715614e235781810291811580156157dd575b6157bb5760009260001992838382098280821091030392670de0b6b3a76400009184831180156157b2575b615767575b50505050505090565b7faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac1066994959650098093828211900360ee1b910360121c170291821415901515160138808080808061575e565b96508596615759565b5050670de0b6b3a7640000808204910615158061570357156131715760010190565b50806157e98385611a97565b1461572e565b81811715614e235781810291811580156158a6575b61588a5760009260001992838382098280821091030392612710918483118015615881575b6158365750505050505090565b7fbc01a36e2eb1c432ca57a786c226809d495182a9930be0ded288ce703afb7e9194959650098093828211900360fc1b910360041c170291821415901515160138808080808061575e565b96508596615829565b5050612710808204910615158061570357156131715760010190565b50806158b28385611a97565b14615804565b670de0b6b3a764000080821715614b53578215614d5357808202821580156158f0575b6156d857908391600094615619575050505090565b50816158fc8483611a97565b146158db565b81811715614e235781810291811580156157dd576157bb5760009260001992838382098280821091030392670de0b6b3a76400009184831180156157b2576157675750505050505090565b6702c68af0bb14000081811715614e23578181029180828404146157bb5760009260001992838382098280821091030392670de0b6b3a76400009184831180156157b2576157675750505050505090565b670de0b6b3a76400009081811715614e23578181029181158015615a6b575b615a4957600092600019928383820982808210910303926702c68af0bb140000918483118015615a40575b6159f55750505050505090565b7f5ff7786fcb32f6f86690bf7c4dc899aa6468a3b109ac0347c75429d9e5c5200d94959650098093828211900360ee1b910360121c170291821415901515160138808080808061575e565b965085966159e8565b50506702c68af0bb140000808204910615158061570357156131715760010190565b5080615a778385611a97565b146159bd565b6f4b3b4ca85a86c47a098a22400000000080821715614b53578215614d5357808202821580156158f0576156d857908391600094615619575050505090565b908115615c4b57600082700100000000000000000000000000000000811015615c3d575b68010000000000000000811015615c28575b640100000000811015615c13575b62010000811015615bfe575b610100811015615be9575b6010811015615bd4575b6004811015615bbf575b60021115615b9d575b60018091811c1b906000905b60078210615b8557505080928115908282159182615b72575b5050615b63575050565b9091925061199d576000190190565b615b7c9250611a97565b82118238615b59565b82615b9282939487611a97565b01811c920190615b40565b6001810180911115615b3457634e487b7160e01b600052601160045260246000fd5b60021c906002810180911161199d5790615b2b565b60041c906004810180911161199d5790615b21565b60081c906008810180911161199d5790615b17565b60101c906010810180911161199d5790615b0c565b60201c906020810180911161199d5790615b00565b60401c906040810180911161199d5790615af2565b50508160801c608090615ae0565b60009150565b8015615ec957806000700100000000000000000000000000000000821015615ebc575b68010000000000000000831015615eb0575b640100000000831015615ea4575b62010000831015615e98575b610100831015615e8c575b6010831015615e80575b600260049384811015615e75575b1015615e6d575b600190818101808211615e42576058811115615e57577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa98201908111615e4257809484821c9484831b906000198201918211615e2d57167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa88401838111615e2d5785901b808211918215615e12575b5050615da7575b5050505060a88211615d91575b6affffffffffffffffffffff6bff000000000000000000000091169160581b161790565b5060a890506affffffffffffffffffffff615d6d565b909192809401936b0100000000000000000000008503615d60577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa9294919395501c9301809211615dfd57509038808080615d60565b601190634e487b7160e01b6000525260246000fd5b14905080615e22575b3880615d59565b508380861614615e1b565b601183634e487b7160e01b6000525260246000fd5b601185634e487b7160e01b6000525260246000fd5b5050506bffffffffffffffffffffffff91501690565b600101615cca565b91810191811c615cc3565b600492831c9201615cb5565b600892831c9201615cab565b601092831c9201615ca0565b602092831c9201615c94565b604092831c9201615c86565b50608081811c9250615c74565b50600090565b77ffffffffffffffffffffffff0000000000000000000000007fffffffffffffffff000000000000000000000000000000000000000000000000615f43615f3d615f376bffffffffffffffffffffffff95989796986000526005602052600260406000200190565b97615c51565b94615c51565b9460c01b169360601b1691161717905556fea2646970667358221220ce6437453674ef316bebdc9aca2ce719eb24bc6b69622a421c51115948b83c5264736f6c63430008180033