Gate Layer is live! View your transactions on  Gate Layer Explorer .
gate
GT Price:$7.01-1.54%
Med Gas Fee:11 NANOGT
Account Details
Contracts0x119c4192aa136d68c310de01c3ad1993e9511c75

Overview

GT Balance

0 GT($0)

Token Holdings

0 Tokens

More Info

Contract Source Code Verified (Exact Match)
Contract Name
EntryPoint
Optimization

Yes, with

200

runs

Compiler
solidity
Compiler Version
v0.8.30+commit.73712a01.js
Other Settings

cancun

evmVersion

MIT

License

</> Contract source code
pragma solidity ^0.8.24;

interface IERC5267 {

    event EIP712DomainChanged();

    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}

library SafeCast {

    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    error SafeCastOverflowedIntToUint(int256 value);

    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    error SafeCastOverflowedUintToInt(uint256 value);

    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    function toInt256(uint256 value) internal pure returns (int256) {

        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    function toUint(bool b) internal pure returns (uint256 u) {
        assembly ("memory-safe") {
            u := iszero(iszero(b))
        }
    }
}

library Panic {

    uint256 internal constant GENERIC = 0x00;

    uint256 internal constant ASSERT = 0x01;

    uint256 internal constant UNDER_OVERFLOW = 0x11;

    uint256 internal constant DIVISION_BY_ZERO = 0x12;

    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;

    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;

    uint256 internal constant EMPTY_ARRAY_POP = 0x31;

    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;

    uint256 internal constant RESOURCE_ERROR = 0x41;

    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;

    function panic(uint256 code) internal pure {
        assembly ("memory-safe") {
            mstore(0x00, 0x4e487b71)
            mstore(0x20, code)
            revert(0x1c, 0x24)
        }
    }
}

library Math {
    enum Rounding {
        Floor,
        Ceil,
        Trunc,
        Expand
    }

    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {

            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {

            return b ^ ((a ^ b) * SafeCast.toUint(condition));
        }
    }

    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return ternary(a > b, a, b);
    }

    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return ternary(a < b, a, b);
    }

    function average(uint256 a, uint256 b) internal pure returns (uint256) {

        return (a & b) + (a ^ b) / 2;
    }

    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {

            Panic.panic(Panic.DIVISION_BY_ZERO);
        }

        unchecked {
            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
        }
    }

    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {

            uint256 prod0 = x * y;
            uint256 prod1;
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            if (prod1 == 0) {

                return prod0 / denominator;
            }

            if (denominator <= prod1) {
                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
            }

            uint256 remainder;
            assembly {

                remainder := mulmod(x, y, denominator)

                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            uint256 twos = denominator & (0 - denominator);
            assembly {

                denominator := div(denominator, twos)

                prod0 := div(prod0, twos)

                twos := add(div(sub(0, twos), twos), 1)
            }

            prod0 |= prod1 * twos;

            uint256 inverse = (3 * denominator) ^ 2;

            inverse *= 2 - denominator * inverse;
            inverse *= 2 - denominator * inverse;
            inverse *= 2 - denominator * inverse;
            inverse *= 2 - denominator * inverse;
            inverse *= 2 - denominator * inverse;
            inverse *= 2 - denominator * inverse;

            result = prod0 * inverse;
            return result;
        }
    }

    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
    }

    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
        unchecked {
            if (n == 0) return 0;

            uint256 remainder = a % n;
            uint256 gcd = n;

            int256 x = 0;
            int256 y = 1;

            while (remainder != 0) {
                uint256 quotient = gcd / remainder;

                (gcd, remainder) = (

                    remainder,

                    gcd - remainder * quotient
                );

                (x, y) = (

                    y,

                    x - y * int256(quotient)
                );
            }

            if (gcd != 1) return 0;
            return ternary(x < 0, n - uint256(-x), uint256(x));
        }
    }

    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
        unchecked {
            return Math.modExp(a, p - 2, p);
        }
    }

    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
        (bool success, uint256 result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
        if (m == 0) return (false, 0);
        assembly ("memory-safe") {
            let ptr := mload(0x40)

            mstore(ptr, 0x20)
            mstore(add(ptr, 0x20), 0x20)
            mstore(add(ptr, 0x40), 0x20)
            mstore(add(ptr, 0x60), b)
            mstore(add(ptr, 0x80), e)
            mstore(add(ptr, 0xa0), m)

            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
            result := mload(0x00)
        }
    }

    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
        (bool success, bytes memory result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    function tryModExp(
        bytes memory b,
        bytes memory e,
        bytes memory m
    ) internal view returns (bool success, bytes memory result) {
        if (_zeroBytes(m)) return (false, new bytes(0));

        uint256 mLen = m.length;

        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);

        assembly ("memory-safe") {
            let dataPtr := add(result, 0x20)

            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)

            mstore(result, mLen)

            mstore(0x40, add(dataPtr, mLen))
        }
    }

    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
        for (uint256 i = 0; i < byteArray.length; ++i) {
            if (byteArray[i] != 0) {
                return false;
            }
        }
        return true;
    }

    function sqrt(uint256 a) internal pure returns (uint256) {
        unchecked {

            if (a <= 1) {
                return a;
            }

            uint256 aa = a;
            uint256 xn = 1;

            if (aa >= (1 << 128)) {
                aa >>= 128;
                xn <<= 64;
            }
            if (aa >= (1 << 64)) {
                aa >>= 64;
                xn <<= 32;
            }
            if (aa >= (1 << 32)) {
                aa >>= 32;
                xn <<= 16;
            }
            if (aa >= (1 << 16)) {
                aa >>= 16;
                xn <<= 8;
            }
            if (aa >= (1 << 8)) {
                aa >>= 8;
                xn <<= 4;
            }
            if (aa >= (1 << 4)) {
                aa >>= 4;
                xn <<= 2;
            }
            if (aa >= (1 << 2)) {
                xn <<= 1;
            }

            xn = (3 * xn) >> 1;

            xn = (xn + a / xn) >> 1;
            xn = (xn + a / xn) >> 1;
            xn = (xn + a / xn) >> 1;
            xn = (xn + a / xn) >> 1;
            xn = (xn + a / xn) >> 1;
            xn = (xn + a / xn) >> 1;

            return xn - SafeCast.toUint(xn > a / xn);
        }
    }

    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
        }
    }

    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        uint256 exp;
        unchecked {
            exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
            value >>= exp;
            result += exp;

            exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
            value >>= exp;
            result += exp;

            exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
            value >>= exp;
            result += exp;

            exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
            value >>= exp;
            result += exp;

            exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
            value >>= exp;
            result += exp;

            exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
            value >>= exp;
            result += exp;

            exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
            value >>= exp;
            result += exp;

            result += SafeCast.toUint(value > 1);
        }
        return result;
    }

    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
        }
    }

    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
        }
    }

    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        uint256 isGt;
        unchecked {
            isGt = SafeCast.toUint(value > (1 << 128) - 1);
            value >>= isGt * 128;
            result += isGt * 16;

            isGt = SafeCast.toUint(value > (1 << 64) - 1);
            value >>= isGt * 64;
            result += isGt * 8;

            isGt = SafeCast.toUint(value > (1 << 32) - 1);
            value >>= isGt * 32;
            result += isGt * 4;

            isGt = SafeCast.toUint(value > (1 << 16) - 1);
            value >>= isGt * 16;
            result += isGt * 2;

            result += SafeCast.toUint(value > (1 << 8) - 1);
        }
        return result;
    }

    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
        }
    }

    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

library SignedMath {

    function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
        unchecked {

            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
        }
    }

    function max(int256 a, int256 b) internal pure returns (int256) {
        return ternary(a > b, a, b);
    }

    function min(int256 a, int256 b) internal pure returns (int256) {
        return ternary(a < b, a, b);
    }

    function average(int256 a, int256 b) internal pure returns (int256) {

        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    function abs(int256 n) internal pure returns (uint256) {
        unchecked {

            int256 mask = n >> 255;

            return uint256((n + mask) ^ mask);
        }
    }
}

library Strings {
    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    error StringsInsufficientHexLength(uint256 value, uint256 length);

    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            assembly ("memory-safe") {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                assembly ("memory-safe") {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        uint256 localValue = value;
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = HEX_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        return string(buffer);
    }

    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
    }

    function toChecksumHexString(address addr) internal pure returns (string memory) {
        bytes memory buffer = bytes(toHexString(addr));

        uint256 hashValue;
        assembly ("memory-safe") {
            hashValue := shr(96, keccak256(add(buffer, 0x22), 40))
        }

        for (uint256 i = 41; i > 1; --i) {

            if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {

                buffer[i] ^= 0x20;
            }
            hashValue >>= 4;
        }
        return string(buffer);
    }

    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

library MessageHashUtils {

    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {
        assembly ("memory-safe") {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, messageHash)
            digest := keccak256(0x00, 0x3c)
        }
    }

    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {
        return
            keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
    }

    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(hex"19_00", validator, data));
    }

    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            mstore(ptr, hex"19_01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            digest := keccak256(ptr, 0x42)
        }
    }
}

library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct Int256Slot {
        int256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }

    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }
}

type ShortString is bytes32;

library ShortStrings {

    bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;

    error StringTooLong(string str);
    error InvalidShortString();

    function toShortString(string memory str) internal pure returns (ShortString) {
        bytes memory bstr = bytes(str);
        if (bstr.length > 31) {
            revert StringTooLong(str);
        }
        return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
    }

    function toString(ShortString sstr) internal pure returns (string memory) {
        uint256 len = byteLength(sstr);

        string memory str = new string(32);
        assembly ("memory-safe") {
            mstore(str, len)
            mstore(add(str, 0x20), sstr)
        }
        return str;
    }

    function byteLength(ShortString sstr) internal pure returns (uint256) {
        uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;
        if (result > 31) {
            revert InvalidShortString();
        }
        return result;
    }

    function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {
        if (bytes(value).length < 32) {
            return toShortString(value);
        } else {
            StorageSlot.getStringSlot(store).value = value;
            return ShortString.wrap(FALLBACK_SENTINEL);
        }
    }

    function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
        if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
            return toString(value);
        } else {
            return store;
        }
    }

    function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {
        if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
            return byteLength(value);
        } else {
            return bytes(store).length;
        }
    }
}

abstract contract EIP712 is IERC5267 {
    using ShortStrings for *;

    bytes32 private constant TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    bytes32 private immutable _cachedDomainSeparator;
    uint256 private immutable _cachedChainId;
    address private immutable _cachedThis;

    bytes32 private immutable _hashedName;
    bytes32 private immutable _hashedVersion;

    ShortString private immutable _name;
    ShortString private immutable _version;
    string private _nameFallback;
    string private _versionFallback;

    constructor(string memory name, string memory version) {
        _name = name.toShortStringWithFallback(_nameFallback);
        _version = version.toShortStringWithFallback(_versionFallback);
        _hashedName = keccak256(bytes(name));
        _hashedVersion = keccak256(bytes(version));

        _cachedChainId = block.chainid;
        _cachedDomainSeparator = _buildDomainSeparator();
        _cachedThis = address(this);
    }

    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
            return _cachedDomainSeparator;
        } else {
            return _buildDomainSeparator();
        }
    }

    function _buildDomainSeparator() private view returns (bytes32) {
        return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
    }

    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
    }

    function eip712Domain()
        external
        view
        virtual
        override
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        return (
            hex"0f",
            _EIP712Name(),
            _EIP712Version(),
            block.chainid,
            address(this),
            bytes32(0),
            new uint256[](0)
        );
    }

    function _EIP712Name() internal view returns (string memory) {
        return _name.toStringWithFallback(_nameFallback);
    }

    function _EIP712Version() internal view returns (string memory) {
        return _version.toStringWithFallback(_versionFallback);
    }
}

interface IERC165 {

    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

abstract contract ERC165 is IERC165 {

    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

library TransientSlot {

    type AddressSlot is bytes32;

    function asAddress(bytes32 slot) internal pure returns (AddressSlot) {
        return AddressSlot.wrap(slot);
    }

    type BooleanSlot is bytes32;

    function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {
        return BooleanSlot.wrap(slot);
    }

    type Bytes32Slot is bytes32;

    function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {
        return Bytes32Slot.wrap(slot);
    }

    type Uint256Slot is bytes32;

    function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {
        return Uint256Slot.wrap(slot);
    }

    type Int256Slot is bytes32;

    function asInt256(bytes32 slot) internal pure returns (Int256Slot) {
        return Int256Slot.wrap(slot);
    }

    function tload(AddressSlot slot) internal view returns (address value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    function tstore(AddressSlot slot, address value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }

    function tload(BooleanSlot slot) internal view returns (bool value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    function tstore(BooleanSlot slot, bool value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }

    function tload(Bytes32Slot slot) internal view returns (bytes32 value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    function tstore(Bytes32Slot slot, bytes32 value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }

    function tload(Uint256Slot slot) internal view returns (uint256 value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    function tstore(Uint256Slot slot, uint256 value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }

    function tload(Int256Slot slot) internal view returns (int256 value) {
        assembly ("memory-safe") {
            value := tload(slot)
        }
    }

    function tstore(Int256Slot slot, int256 value) internal {
        assembly ("memory-safe") {
            tstore(slot, value)
        }
    }
}

abstract contract ReentrancyGuardTransient {
    using TransientSlot for *;

    bytes32 private constant REENTRANCY_GUARD_STORAGE =
        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

    error ReentrancyGuardReentrantCall();

    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {

        if (_reentrancyGuardEntered()) {
            revert ReentrancyGuardReentrantCall();
        }

        REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);
    }

    function _nonReentrantAfter() private {
        REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);
    }

    function _reentrancyGuardEntered() internal view returns (bool) {
        return REENTRANCY_GUARD_STORAGE.asBoolean().tload();
    }
}

uint256 constant SIG_VALIDATION_FAILED = 1;

uint256 constant SIG_VALIDATION_SUCCESS = 0;

struct ValidationData {
    address aggregator;
    uint48 validAfter;
    uint48 validUntil;
}

function _parseValidationData(
    uint256 validationData
) pure returns (ValidationData memory result) {
    address aggregator = address(uint160(validationData));
    uint48 validUntil = uint48(validationData >> 160);
    if (validUntil == 0) {
        validUntil = type(uint48).max;
    }
    uint48 validAfter = uint48(validationData >> (48 + 160));
    return ValidationData(aggregator, validAfter, validUntil);
}

function _packValidationData(
    ValidationData memory validationData
) pure returns (uint256) {
    return
        uint160(validationData.aggregator) |
        (uint256(validationData.validUntil) << 160) |
        (uint256(validationData.validAfter) << (160 + 48));
}

function _packValidationData(
    bool sigFailed,
    uint48 validUntil,
    uint48 validAfter
) pure returns (uint256) {
    return
        (sigFailed ?  SIG_VALIDATION_FAILED : SIG_VALIDATION_SUCCESS) |
        (uint256(validUntil) << 160) |
        (uint256(validAfter) << (160 + 48));
}

    function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
        assembly ("memory-safe") {
            let mem := mload(0x40)
            let len := data.length
            calldatacopy(mem, data.offset, len)
            ret := keccak256(mem, len)
        }
    }

    function min256(uint256 a, uint256 b) pure returns (uint256) {
        return a < b ? a : b;
    }

    function finalizeAllocation(uint256 memPointer, uint256 allocationSize) pure {

        assembly ("memory-safe"){
            finalize_allocation(memPointer, allocationSize)

            function finalize_allocation(memPtr, size) {
                let newFreePtr := add(memPtr, round_up_to_mul_of_32(size))
                mstore(64, newFreePtr)
            }

            function round_up_to_mul_of_32(value) -> result {
                result := and(add(value, 31), not(31))
            }
        }
    }

struct PackedUserOperation {
    address sender;
    uint256 nonce;
    bytes initCode;
    bytes callData;
    bytes32 accountGasLimits;
    uint256 preVerificationGas;
    bytes32 gasFees;
    bytes paymasterAndData;
    bytes signature;
}

library UserOperationLib {

    uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;
    uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;
    uint256 public constant PAYMASTER_DATA_OFFSET = 52;

    function gasPrice(
        PackedUserOperation calldata userOp
    ) internal view returns (uint256) {
        unchecked {
            (uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees);
            return min256(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
        }
    }

    bytes32 internal constant PACKED_USEROP_TYPEHASH =
    keccak256(
        "PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)"
    );

    function encode(
        PackedUserOperation calldata userOp,
        bytes32 overrideInitCodeHash
    ) internal pure returns (bytes memory ret) {
        address sender = userOp.sender;
        uint256 nonce = userOp.nonce;
        bytes32 hashInitCode = overrideInitCodeHash != 0 ? overrideInitCodeHash : calldataKeccak(userOp.initCode);
        bytes32 hashCallData = calldataKeccak(userOp.callData);
        bytes32 accountGasLimits = userOp.accountGasLimits;
        uint256 preVerificationGas = userOp.preVerificationGas;
        bytes32 gasFees = userOp.gasFees;
        bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);

        return abi.encode(
            UserOperationLib.PACKED_USEROP_TYPEHASH,
            sender, nonce,
            hashInitCode, hashCallData,
            accountGasLimits, preVerificationGas, gasFees,
            hashPaymasterAndData
        );
    }

    function unpackUints(
        bytes32 packed
    ) internal pure returns (uint256 high128, uint256 low128) {
        return (unpackHigh128(packed), unpackLow128(packed));
    }

    function unpackHigh128(bytes32 packed) internal pure returns (uint256) {
        return uint256(packed) >> 128;
    }

    function unpackLow128(bytes32 packed) internal pure returns (uint256) {
        return uint128(uint256(packed));
    }

    function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return unpackHigh128(userOp.gasFees);
    }

    function unpackMaxFeePerGas(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return unpackLow128(userOp.gasFees);
    }

    function unpackVerificationGasLimit(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return unpackHigh128(userOp.accountGasLimits);
    }

    function unpackCallGasLimit(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return unpackLow128(userOp.accountGasLimits);
    }

    function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET]));
    }

    function unpackPostOpGasLimit(PackedUserOperation calldata userOp)
    internal pure returns (uint256) {
        return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]));
    }

    function unpackPaymasterStaticFields(
        bytes calldata paymasterAndData
    ) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) {
        return (
            address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])),
            uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])),
            uint128(bytes16(paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]))
        );
    }

    function hash(
        PackedUserOperation calldata userOp,
        bytes32 overrideInitCodeHash
    ) internal pure returns (bytes32) {
        return keccak256(encode(userOp, overrideInitCodeHash));
    }
}

library Eip7702Support {

    bytes3 internal constant EIP7702_PREFIX = 0xef0100;

    bytes2 internal constant INITCODE_EIP7702_MARKER = 0x7702;

    using UserOperationLib for PackedUserOperation;

    function _getEip7702InitCodeHashOverride(PackedUserOperation calldata userOp) internal view returns (bytes32) {
        bytes calldata initCode = userOp.initCode;
        if (!_isEip7702InitCode(initCode)) {
            return 0;
        }
        address delegate = _getEip7702Delegate(userOp.sender);
        if (initCode.length <= 20)
            return keccak256(abi.encodePacked(delegate));
        else
            return keccak256(abi.encodePacked(delegate, initCode[20 :]));
    }

    function _isEip7702InitCode(bytes calldata initCode) internal pure returns (bool) {

        if (initCode.length < 2) {
            return false;
        }
        bytes20 initCodeStart;

        assembly ("memory-safe") {
            initCodeStart := calldataload(initCode.offset)
        }

        return initCodeStart == bytes20(INITCODE_EIP7702_MARKER);
    }

    function _getEip7702Delegate(address sender) internal view returns (address) {

        bytes32 senderCode;

        assembly ("memory-safe") {
            extcodecopy(sender, 0, 0, 23)
            senderCode := mload(0)
        }

        if (bytes3(senderCode) != EIP7702_PREFIX) {

            require(sender.code.length > 0, "sender has no code");
            revert("not an EIP-7702 delegate");
        }
        return address(bytes20(senderCode << 24));
    }
}

interface INonceManager {

    function getNonce(address sender, uint192 key)
    external view returns (uint256 nonce);

    function incrementNonce(uint192 key) external;
}

abstract contract NonceManager is INonceManager {

    mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;

    function getNonce(address sender, uint192 key)
    external view override returns (uint256 nonce) {
        return nonceSequenceNumber[sender][key] | (uint256(key) << 64);
    }

    function incrementNonce(uint192 key) external override {
        nonceSequenceNumber[msg.sender][key]++;
    }

    function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {

        uint192 key = uint192(nonce >> 64);
        uint64 seq = uint64(nonce);
        return nonceSequenceNumber[sender][key]++ == seq;
    }

}

interface IAggregator {

    function validateSignatures(
        PackedUserOperation[] calldata userOps,
        bytes calldata signature
    ) external;

    function validateUserOpSignature(
        PackedUserOperation calldata userOp
    ) external view returns (bytes memory sigForUserOp);

    function aggregateSignatures(
        PackedUserOperation[] calldata userOps
    ) external view returns (bytes memory aggregatedSignature);
}

interface ISenderCreator {

    function createSender(bytes calldata initCode) external returns (address sender);

    function initEip7702Sender(address sender, bytes calldata initCallData) external;
}

interface IStakeManager {
    event Deposited(address indexed account, uint256 totalDeposit);

    event Withdrawn(
        address indexed account,
        address withdrawAddress,
        uint256 amount
    );

    event StakeLocked(
        address indexed account,
        uint256 totalStaked,
        uint256 unstakeDelaySec
    );

    event StakeUnlocked(address indexed account, uint256 withdrawTime);

    event StakeWithdrawn(
        address indexed account,
        address withdrawAddress,
        uint256 amount
    );

    struct DepositInfo {
        uint256 deposit;
        bool staked;
        uint112 stake;
        uint32 unstakeDelaySec;
        uint48 withdrawTime;
    }

    struct StakeInfo {
        uint256 stake;
        uint256 unstakeDelaySec;
    }

    function getDepositInfo(
        address account
    ) external view returns (DepositInfo memory info);

    function balanceOf(address account) external view returns (uint256);

    function depositTo(address account) external payable;

    function addStake(uint32 unstakeDelaySec) external payable;

    function unlockStake() external;

    function withdrawStake(address payable withdrawAddress) external;

    function withdrawTo(
        address payable withdrawAddress,
        uint256 withdrawAmount
    ) external;
}

interface IEntryPoint is IStakeManager, INonceManager {

    event UserOperationEvent(
        bytes32 indexed userOpHash,
        address indexed sender,
        address indexed paymaster,
        uint256 nonce,
        bool success,
        uint256 actualGasCost,
        uint256 actualGasUsed
    );

    event AccountDeployed(
        bytes32 indexed userOpHash,
        address indexed sender,
        address factory,
        address paymaster
    );

    event UserOperationRevertReason(
        bytes32 indexed userOpHash,
        address indexed sender,
        uint256 nonce,
        bytes revertReason
    );

    event PostOpRevertReason(
        bytes32 indexed userOpHash,
        address indexed sender,
        uint256 nonce,
        bytes revertReason
    );

    event UserOperationPrefundTooLow(
        bytes32 indexed userOpHash,
        address indexed sender,
        uint256 nonce
    );

    event BeforeExecution();

    event SignatureAggregatorChanged(address indexed aggregator);

    error FailedOp(uint256 opIndex, string reason);

    error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);

    error PostOpReverted(bytes returnData);

    error SignatureValidationFailed(address aggregator);

    error SenderAddressResult(address sender);

    struct UserOpsPerAggregator {
        PackedUserOperation[] userOps;

        IAggregator aggregator;

        bytes signature;
    }

    function handleOps(
        PackedUserOperation[] calldata ops,
        address payable beneficiary
    ) external;

    function handleAggregatedOps(
        UserOpsPerAggregator[] calldata opsPerAggregator,
        address payable beneficiary
    ) external;

    function getUserOpHash(
        PackedUserOperation calldata userOp
    ) external view returns (bytes32);

    struct ReturnInfo {
        uint256 preOpGas;
        uint256 prefund;
        uint256 accountValidationData;
        uint256 paymasterValidationData;
        bytes paymasterContext;
    }

    function getSenderAddress(bytes memory initCode) external;

    error DelegateAndRevert(bool success, bytes ret);

    function delegateAndRevert(address target, bytes calldata data) external;

    function senderCreator() external view returns (ISenderCreator);
}

library Exec {

    function call(
        address to,
        uint256 value,
        bytes memory data,
        uint256 txGas
    ) internal returns (bool success) {
        assembly ("memory-safe") {
            success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
        }
    }

    function staticcall(
        address to,
        bytes memory data,
        uint256 txGas
    ) internal view returns (bool success) {
        assembly ("memory-safe") {
            success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)
        }
    }

    function delegateCall(
        address to,
        bytes memory data,
        uint256 txGas
    ) internal returns (bool success) {
        assembly ("memory-safe") {
            success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
        }
    }

    function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {
        assembly ("memory-safe") {
            let len := returndatasize()
            if gt(maxLen,0) {
                if gt(len, maxLen) {
                    len := maxLen
                }
            }
            let ptr := mload(0x40)
            mstore(0x40, add(ptr, add(len, 0x20)))
            mstore(ptr, len)
            returndatacopy(add(ptr, 0x20), 0, len)
            returnData := ptr
        }
    }

    function revertWithData(bytes memory returnData) internal pure {
        assembly ("memory-safe") {
            revert(add(returnData, 32), mload(returnData))
        }
    }

    function revertWithReturnData() internal pure {
        revertWithData(getReturnData(0));
    }
}

contract SenderCreator is ISenderCreator {
    address public immutable entryPoint;

    constructor(){
        entryPoint = msg.sender;
    }

    uint256 private constant REVERT_REASON_MAX_LEN = 2048;

    function createSender(
        bytes calldata initCode
    ) external returns (address sender) {
        require(msg.sender == entryPoint, "AA97 should call from EntryPoint");
        address factory = address(bytes20(initCode[0 : 20]));

        bytes memory initCallData = initCode[20 :];
        bool success;
        assembly ("memory-safe") {
            success := call(
                gas(),
                factory,
                0,
                add(initCallData, 0x20),
                mload(initCallData),
                0,
                32
            )
            if success {
                sender := mload(0)
            }
        }
    }

    function initEip7702Sender(
        address sender,
        bytes memory initCallData
    ) external {
        require(msg.sender == entryPoint, "AA97 should call from EntryPoint");
        bool success;
        assembly ("memory-safe") {
            success := call(
                gas(),
                sender,
                0,
                add(initCallData, 0x20),
                mload(initCallData),
                0,
                0
            )
        }
        if (!success) {
            bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);
            revert IEntryPoint.FailedOpWithRevert(0, "AA13 EIP7702 sender init failed", result);
        }
    }
}

abstract contract StakeManager is IStakeManager {

    mapping(address => DepositInfo) private deposits;

    function getDepositInfo(
        address account
    ) external view override returns (DepositInfo memory info) {
        return deposits[account];
    }

    function _getStakeInfo(
        address addr
    ) internal view returns (StakeInfo memory info) {
        DepositInfo storage depositInfo = deposits[addr];
        info.stake = depositInfo.stake;
        info.unstakeDelaySec = depositInfo.unstakeDelaySec;
    }

    function balanceOf(address account) public view override returns (uint256) {
        return deposits[account].deposit;
    }

    receive() external payable {
        depositTo(msg.sender);
    }

    function _incrementDeposit(address account, uint256 amount) internal returns (uint256) {
        unchecked {
            DepositInfo storage info = deposits[account];
            uint256 newAmount = info.deposit + amount;
            info.deposit = newAmount;
            return newAmount;
        }
    }

    function _tryDecrementDeposit(address account, uint256 amount) internal returns(bool) {
        unchecked {
            DepositInfo storage info = deposits[account];
            uint256 currentDeposit = info.deposit;
            if (currentDeposit < amount) {
                return false;
            }
            info.deposit = currentDeposit - amount;
            return true;
        }
    }

    function depositTo(address account) public payable override {
        uint256 newDeposit = _incrementDeposit(account, msg.value);
        emit Deposited(account, newDeposit);
    }

    function addStake(uint32 unstakeDelaySec) external payable override {
        DepositInfo storage info = deposits[msg.sender];
        require(unstakeDelaySec > 0, "must specify unstake delay");
        require(
            unstakeDelaySec >= info.unstakeDelaySec,
            "cannot decrease unstake time"
        );
        uint256 stake = info.stake + msg.value;
        require(stake > 0, "no stake specified");
        require(stake <= type(uint112).max, "stake overflow");
        deposits[msg.sender] = DepositInfo(
            info.deposit,
            true,
            uint112(stake),
            unstakeDelaySec,
            0
        );
        emit StakeLocked(msg.sender, stake, unstakeDelaySec);
    }

    function unlockStake() external override {
        DepositInfo storage info = deposits[msg.sender];
        require(info.unstakeDelaySec != 0, "not staked");
        require(info.staked, "already unstaking");
        uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;
        info.withdrawTime = withdrawTime;
        info.staked = false;
        emit StakeUnlocked(msg.sender, withdrawTime);
    }

    function withdrawStake(address payable withdrawAddress) external override {
        DepositInfo storage info = deposits[msg.sender];
        uint256 stake = info.stake;
        require(stake > 0, "No stake to withdraw");
        require(info.withdrawTime > 0, "must call unlockStake() first");
        require(
            info.withdrawTime <= block.timestamp,
            "Stake withdrawal is not due"
        );
        info.unstakeDelaySec = 0;
        info.withdrawTime = 0;
        info.stake = 0;
        emit StakeWithdrawn(msg.sender, withdrawAddress, stake);
        (bool success,) = withdrawAddress.call{value: stake}("");
        require(success, "failed to withdraw stake");
    }

    function withdrawTo(
        address payable withdrawAddress,
        uint256 withdrawAmount
    ) external override {
        DepositInfo storage info = deposits[msg.sender];
        uint256 currentDeposit = info.deposit;
        require(withdrawAmount <= currentDeposit, "Withdraw amount too large");
        info.deposit = currentDeposit - withdrawAmount;
        emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);
        (bool success,) = withdrawAddress.call{value: withdrawAmount}("");
        require(success, "failed to withdraw");
    }
}

interface IAccount {

    function validateUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external returns (uint256 validationData);
}

interface IAccountExecute {

    function executeUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash
    ) external;
}

interface IPaymaster {
    enum PostOpMode {

        opSucceeded,

        opReverted,

        postOpReverted
    }

    function validatePaymasterUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 maxCost
    ) external returns (bytes memory context, uint256 validationData);

    function postOp(
        PostOpMode mode,
        bytes calldata context,
        uint256 actualGasCost,
        uint256 actualUserOpFeePerGas
    ) external;
}

contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardTransient, ERC165, EIP712 {

    using UserOperationLib for PackedUserOperation;

    uint256 private constant INNER_GAS_OVERHEAD = 10000;

    bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead";
    bytes32 private constant INNER_REVERT_LOW_PREFUND = hex"deadaa51";

    uint256 private constant REVERT_REASON_MAX_LEN = 2048;

    uint256 private constant UNUSED_GAS_PENALTY_PERCENT = 10;

    uint256 private constant PENALTY_GAS_THRESHOLD = 40000;

    SenderCreator private immutable _senderCreator = new SenderCreator();

    string constant internal DOMAIN_NAME = "ERC4337";
    string constant internal DOMAIN_VERSION = "1";

    constructor() EIP712(DOMAIN_NAME, DOMAIN_VERSION)  {
    }

    function handleOps(
        PackedUserOperation[] calldata ops,
        address payable beneficiary
    ) external override nonReentrant {
        uint256 opslen = ops.length;
        UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);
        unchecked {
            _iterateValidationPhase(ops, opInfos, address(0), 0);

            uint256 collected = 0;
            emit BeforeExecution();

            for (uint256 i = 0; i < opslen; i++) {
                collected += _executeUserOp(i, ops[i], opInfos[i]);
            }

            _compensate(beneficiary, collected);
        }
    }

    function handleAggregatedOps(
        UserOpsPerAggregator[] calldata opsPerAggregator,
        address payable beneficiary
    ) external override nonReentrant {

        unchecked {
            uint256 opasLen = opsPerAggregator.length;
            uint256 totalOps = 0;
            for (uint256 i = 0; i < opasLen; i++) {
                UserOpsPerAggregator calldata opa = opsPerAggregator[i];
                PackedUserOperation[] calldata ops = opa.userOps;
                IAggregator aggregator = opa.aggregator;

                require(
                    address(aggregator) != address(1),
                    SignatureValidationFailed(address(aggregator))
                );

                if (address(aggregator) != address(0)) {

                    try aggregator.validateSignatures(ops, opa.signature) {} catch {
                        revert SignatureValidationFailed(address(aggregator));
                    }
                }

                totalOps += ops.length;
            }

            UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);

            uint256 opIndex = 0;
            for (uint256 a = 0; a < opasLen; a++) {
                UserOpsPerAggregator calldata opa = opsPerAggregator[a];
                PackedUserOperation[] calldata ops = opa.userOps;
                IAggregator aggregator = opa.aggregator;

                opIndex += _iterateValidationPhase(ops, opInfos, address(aggregator), opIndex);
            }

            emit BeforeExecution();

            uint256 collected = 0;
            opIndex = 0;
            for (uint256 a = 0; a < opasLen; a++) {
                UserOpsPerAggregator calldata opa = opsPerAggregator[a];
                emit SignatureAggregatorChanged(address(opa.aggregator));
                PackedUserOperation[] calldata ops = opa.userOps;
                uint256 opslen = ops.length;

                for (uint256 i = 0; i < opslen; i++) {
                    collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);
                    opIndex++;
                }
            }

            _compensate(beneficiary, collected);
        }
    }

    function getUserOpHash(
        PackedUserOperation calldata userOp
    ) public view override returns (bytes32) {
        bytes32 overrideInitCodeHash = Eip7702Support._getEip7702InitCodeHashOverride(userOp);
        return
            MessageHashUtils.toTypedDataHash(getDomainSeparatorV4(), userOp.hash(overrideInitCodeHash));
    }

    function getSenderAddress(bytes memory initCode) external override {
        address sender = senderCreator().createSender(initCode);
        revert SenderAddressResult(sender);
    }

    function senderCreator() public view override returns (ISenderCreator) {
        return _senderCreator;
    }

    function delegateAndRevert(address target, bytes calldata data) external override {
        (bool success, bytes memory ret) = target.delegatecall(data);
        revert DelegateAndRevert(success, ret);
    }

    function getPackedUserOpTypeHash() external pure returns (bytes32) {
        return UserOperationLib.PACKED_USEROP_TYPEHASH;
    }

    function getDomainSeparatorV4() public virtual view returns (bytes32) {
        return _domainSeparatorV4();
    }

    function supportsInterface(bytes4 interfaceId) public view override returns (bool) {

        return interfaceId == (type(IEntryPoint).interfaceId ^ type(IStakeManager).interfaceId ^ type(INonceManager).interfaceId) ||
        interfaceId == type(IEntryPoint).interfaceId ||
        interfaceId == type(IStakeManager).interfaceId ||
        interfaceId == type(INonceManager).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function _compensate(address payable beneficiary, uint256 amount) internal virtual {
        require(beneficiary != address(0), "AA90 invalid beneficiary");
        (bool success,) = beneficiary.call{value: amount}("");
        require(success, "AA91 failed send to beneficiary");
    }

    function _executeUserOp(
        uint256 opIndex,
        PackedUserOperation calldata userOp,
        UserOpInfo memory opInfo
    )
    internal virtual
    returns (uint256 collected) {
        uint256 preGas = gasleft();
        bytes memory context = _getMemoryBytesFromOffset(opInfo.contextOffset);
        bool success;
        {
            uint256 saveFreePtr = _getFreePtr();
            bytes calldata callData = userOp.callData;
            bytes memory innerCall;
            bytes4 methodSig;
            assembly ("memory-safe") {
                let len := callData.length
                if gt(len, 3) {
                    methodSig := calldataload(callData.offset)
                }
            }
            if (methodSig == IAccountExecute.executeUserOp.selector) {
                bytes memory executeUserOp = abi.encodeCall(IAccountExecute.executeUserOp, (userOp, opInfo.userOpHash));
                innerCall = abi.encodeCall(this.innerHandleOp, (executeUserOp, opInfo, context));
            } else
            {
                innerCall = abi.encodeCall(this.innerHandleOp, (callData, opInfo, context));
            }
            assembly ("memory-safe") {
                success := call(gas(), address(), 0, add(innerCall, 0x20), mload(innerCall), 0, 32)
                collected := mload(0)
            }
            _restoreFreePtr(saveFreePtr);
        }
        if (!success) {
            bytes32 innerRevertCode;
            assembly ("memory-safe") {
                let len := returndatasize()
                if eq(32, len) {
                    returndatacopy(0, 0, 32)
                    innerRevertCode := mload(0)
                }
            }
            if (innerRevertCode == INNER_OUT_OF_GAS) {

                revert FailedOp(opIndex, "AA95 out of gas");
            } else if (innerRevertCode == INNER_REVERT_LOW_PREFUND) {

                uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
                uint256 actualGasCost = opInfo.prefund;
                _emitPrefundTooLow(opInfo);
                _emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);
                collected = actualGasCost;
            } else {
                uint256 freePtr = _getFreePtr();
                emit PostOpRevertReason(
                    opInfo.userOpHash,
                    opInfo.mUserOp.sender,
                    opInfo.mUserOp.nonce,
                    Exec.getReturnData(REVERT_REASON_MAX_LEN)
                );
                _restoreFreePtr(freePtr);

                uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
                collected = _postExecution(
                    IPaymaster.PostOpMode.postOpReverted,
                    opInfo,
                    context,
                    actualGas
                );
            }
        }
    }

    function _emitUserOperationEvent(UserOpInfo memory opInfo, bool success, uint256 actualGasCost, uint256 actualGas) internal virtual {
        emit UserOperationEvent(
            opInfo.userOpHash,
            opInfo.mUserOp.sender,
            opInfo.mUserOp.paymaster,
            opInfo.mUserOp.nonce,
            success,
            actualGasCost,
            actualGas
        );
    }

    function _emitPrefundTooLow(UserOpInfo memory opInfo) internal virtual {
        emit UserOperationPrefundTooLow(
            opInfo.userOpHash,
            opInfo.mUserOp.sender,
            opInfo.mUserOp.nonce
        );
    }

    function _iterateValidationPhase(
        PackedUserOperation[] calldata ops,
        UserOpInfo[] memory opInfos,
        address expectedAggregator,
        uint256 opIndexOffset
    ) internal returns (uint256 opsLen){
        unchecked {
            opsLen = ops.length;
            for (uint256 i = 0; i < opsLen; i++) {
                UserOpInfo memory opInfo = opInfos[opIndexOffset + i];
                (
                    uint256 validationData,
                    uint256 pmValidationData
                ) = _validatePrepayment(opIndexOffset + i, ops[i], opInfo);
                _validateAccountAndPaymasterValidationData(
                    opIndexOffset + i,
                    validationData,
                    pmValidationData,
                    expectedAggregator
                );
            }
        }
    }

    struct MemoryUserOp {
        address sender;
        uint256 nonce;
        uint256 verificationGasLimit;
        uint256 callGasLimit;
        uint256 paymasterVerificationGasLimit;
        uint256 paymasterPostOpGasLimit;
        uint256 preVerificationGas;
        address paymaster;
        uint256 maxFeePerGas;
        uint256 maxPriorityFeePerGas;
    }

    struct UserOpInfo {
        MemoryUserOp mUserOp;
        bytes32 userOpHash;
        uint256 prefund;
        uint256 contextOffset;
        uint256 preOpGas;
    }

    function innerHandleOp(
        bytes memory callData,
        UserOpInfo memory opInfo,
        bytes calldata context
    ) external returns (uint256 actualGasCost) {
        uint256 preGas = gasleft();
        require(msg.sender == address(this), "AA92 internal call only");
        MemoryUserOp memory mUserOp = opInfo.mUserOp;

        uint256 callGasLimit = mUserOp.callGasLimit;
        unchecked {

            if (
                gasleft() * 63 / 64 <
                callGasLimit +
                mUserOp.paymasterPostOpGasLimit +
                INNER_GAS_OVERHEAD
            ) {
                assembly ("memory-safe") {
                    mstore(0, INNER_OUT_OF_GAS)
                    revert(0, 32)
                }
            }
        }

        IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;
        if (callData.length > 0) {
            bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);
            if (!success) {
                uint256 freePtr = _getFreePtr();
                bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);
                if (result.length > 0) {
                    emit UserOperationRevertReason(
                        opInfo.userOpHash,
                        mUserOp.sender,
                        mUserOp.nonce,
                        result
                    );
                }
                _restoreFreePtr(freePtr);
                mode = IPaymaster.PostOpMode.opReverted;
            }
        }

        unchecked {
            uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
            return _postExecution(mode, opInfo, context, actualGas);
        }
    }

    function _copyUserOpToMemory(
        PackedUserOperation calldata userOp,
        MemoryUserOp memory mUserOp
    ) internal virtual pure {
        mUserOp.sender = userOp.sender;
        mUserOp.nonce = userOp.nonce;
        (mUserOp.verificationGasLimit, mUserOp.callGasLimit) = UserOperationLib.unpackUints(userOp.accountGasLimits);
        mUserOp.preVerificationGas = userOp.preVerificationGas;
        (mUserOp.maxPriorityFeePerGas, mUserOp.maxFeePerGas) = UserOperationLib.unpackUints(userOp.gasFees);
        bytes calldata paymasterAndData = userOp.paymasterAndData;
        if (paymasterAndData.length > 0) {
            require(
                paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET,
                "AA93 invalid paymasterAndData"
            );
            address paymaster;
            (paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData);
            require(paymaster != address(0), "AA98 invalid paymaster");
            mUserOp.paymaster = paymaster;
        }
    }

    function _getRequiredPrefund(
        MemoryUserOp memory mUserOp
    ) internal virtual pure returns (uint256 requiredPrefund) {
        unchecked {
            uint256 requiredGas = mUserOp.verificationGasLimit +
                            mUserOp.callGasLimit +
                            mUserOp.paymasterVerificationGasLimit +
                            mUserOp.paymasterPostOpGasLimit +
                            mUserOp.preVerificationGas;

            requiredPrefund = requiredGas * mUserOp.maxFeePerGas;
        }
    }

    function _createSenderIfNeeded(
        uint256 opIndex,
        UserOpInfo memory opInfo,
        bytes calldata initCode
    ) internal virtual {
        if (initCode.length != 0) {
            address sender = opInfo.mUserOp.sender;
            if (Eip7702Support._isEip7702InitCode(initCode)) {
                if (initCode.length > 20) {

                    senderCreator().initEip7702Sender{
                            gas: opInfo.mUserOp.verificationGasLimit
                        }(sender, initCode[20 :]);
                }
                return;
            }
            if (sender.code.length != 0)
                revert FailedOp(opIndex, "AA10 sender already constructed");
            if (initCode.length < 20) {
                revert FailedOp(opIndex, "AA99 initCode too small");
            }
            address sender1 = senderCreator().createSender{
                    gas: opInfo.mUserOp.verificationGasLimit
                }(initCode);
            if (sender1 == address(0))
                revert FailedOp(opIndex, "AA13 initCode failed or OOG");
            if (sender1 != sender)
                revert FailedOp(opIndex, "AA14 initCode must return sender");
            if (sender1.code.length == 0)
                revert FailedOp(opIndex, "AA15 initCode must create sender");
            address factory = address(bytes20(initCode[0 : 20]));
            emit AccountDeployed(
                opInfo.userOpHash,
                sender,
                factory,
                opInfo.mUserOp.paymaster
            );
        }
    }

    function _validateAccountPrepayment(
        uint256 opIndex,
        PackedUserOperation calldata op,
        UserOpInfo memory opInfo,
        uint256 requiredPrefund
    )
    internal virtual
    returns (
        uint256 validationData
    )
    {
        unchecked {
            MemoryUserOp memory mUserOp = opInfo.mUserOp;
            address sender = mUserOp.sender;
            _createSenderIfNeeded(opIndex, opInfo, op.initCode);
            address paymaster = mUserOp.paymaster;
            uint256 missingAccountFunds = 0;
            if (paymaster == address(0)) {
                uint256 bal = balanceOf(sender);
                missingAccountFunds = bal > requiredPrefund
                    ? 0
                    : requiredPrefund - bal;
            }
            validationData = _callValidateUserOp(opIndex, op, opInfo, missingAccountFunds);
            if (paymaster == address(0)) {
                if (!_tryDecrementDeposit(sender, requiredPrefund)) {
                    revert FailedOp(opIndex, "AA21 didn't pay prefund");
                }
            }
        }
    }

    function _callValidateUserOp(
        uint256 opIndex,
        PackedUserOperation calldata op,
        UserOpInfo memory opInfo,
        uint256 missingAccountFunds
    )
    internal virtual returns (uint256 validationData) {
        uint256 gasLimit = opInfo.mUserOp.verificationGasLimit;
        address sender = opInfo.mUserOp.sender;
        bool success;
        {
            uint256 saveFreePtr = _getFreePtr();
            bytes memory callData = abi.encodeCall(IAccount.validateUserOp, (op, opInfo.userOpHash, missingAccountFunds));
            assembly ("memory-safe"){
                success := call(gasLimit, sender, 0, add(callData, 0x20), mload(callData), 0, 32)
                validationData := mload(0)

                if iszero(eq(returndatasize(), 32)) {
                    success := 0
                }
            }
            _restoreFreePtr(saveFreePtr);
        }
        if (!success) {
            if (sender.code.length == 0) {
                revert FailedOp(opIndex, "AA20 account not deployed");
            } else {
                revert FailedOpWithRevert(opIndex, "AA23 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN));
            }
        }
    }

    function _validatePaymasterPrepayment(
        uint256 opIndex,
        PackedUserOperation calldata op,
        UserOpInfo memory opInfo
    ) internal virtual returns (bytes memory context, uint256 validationData) {
        unchecked {
            uint256 preGas = gasleft();
            MemoryUserOp memory mUserOp = opInfo.mUserOp;
            address paymaster = mUserOp.paymaster;
            uint256 requiredPreFund = opInfo.prefund;
            if (!_tryDecrementDeposit(paymaster, requiredPreFund)) {
                revert FailedOp(opIndex, "AA31 paymaster deposit too low");
            }
            uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit;
            (context, validationData) = _callValidatePaymasterUserOp(opIndex, op, opInfo);
            if (preGas - gasleft() > pmVerificationGasLimit) {
                revert FailedOp(opIndex, "AA36 over paymasterVerificationGasLimit");
            }
        }
    }

    function _callValidatePaymasterUserOp(
        uint256 opIndex,
        PackedUserOperation calldata op,
        UserOpInfo memory opInfo
    ) internal returns (bytes memory context, uint256 validationData)  {
        uint256 freePtr = _getFreePtr();
        bytes memory validatePaymasterCall = abi.encodeCall(
            IPaymaster.validatePaymasterUserOp,
            (op, opInfo.userOpHash, opInfo.prefund)
        );
        address paymaster = opInfo.mUserOp.paymaster;
        uint256 paymasterVerificationGasLimit = opInfo.mUserOp.paymasterVerificationGasLimit;
        bool success;
        uint256 contextLength;
        uint256 contextOffset;
        uint256 maxContextLength;
        uint256 len;
        assembly ("memory-safe") {
            success := call(paymasterVerificationGasLimit, paymaster, 0, add(validatePaymasterCall, 0x20), mload(validatePaymasterCall), 0, 0)
            len := returndatasize()

            returndatacopy(freePtr, 0, len)
            validationData := mload(add(freePtr, 32))
            contextOffset := mload(freePtr)
            maxContextLength := sub(len, 96)
            context := add(freePtr, 64)
            contextLength := mload(context)
        }

        unchecked {
            if (!success || contextOffset != 64 || contextLength + 31 < maxContextLength) {
                revert FailedOpWithRevert(opIndex, "AA33 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN));
            }
        }
        finalizeAllocation(freePtr, len);
    }

    function _validateAccountAndPaymasterValidationData(
        uint256 opIndex,
        uint256 validationData,
        uint256 paymasterValidationData,
        address expectedAggregator
    ) internal virtual view {
        (address aggregator, bool outOfTimeRange) = _getValidationData(
            validationData
        );
        if (expectedAggregator != aggregator) {
            revert FailedOp(opIndex, "AA24 signature error");
        }
        if (outOfTimeRange) {
            revert FailedOp(opIndex, "AA22 expired or not due");
        }

        address pmAggregator;
        (pmAggregator, outOfTimeRange) = _getValidationData(
            paymasterValidationData
        );
        if (pmAggregator != address(0)) {
            revert FailedOp(opIndex, "AA34 signature error");
        }
        if (outOfTimeRange) {
            revert FailedOp(opIndex, "AA32 paymaster expired or not due");
        }
    }

    function _getValidationData(
        uint256 validationData
    ) internal virtual view returns (address aggregator, bool outOfTimeRange) {
        if (validationData == 0) {
            return (address(0), false);
        }
        ValidationData memory parsedData = _parseValidationData(validationData);

        outOfTimeRange = block.timestamp > parsedData.validUntil || block.timestamp <= parsedData.validAfter;
        aggregator = parsedData.aggregator;
    }

    function _validatePrepayment(
        uint256 opIndex,
        PackedUserOperation calldata userOp,
        UserOpInfo memory outOpInfo
    )
    internal virtual
    returns (uint256 validationData, uint256 paymasterValidationData)
    {
        uint256 preGas = gasleft();
        MemoryUserOp memory mUserOp = outOpInfo.mUserOp;
        _copyUserOpToMemory(userOp, mUserOp);

        uint256 freePtr = _getFreePtr();
        outOpInfo.userOpHash = getUserOpHash(userOp);
        _restoreFreePtr(freePtr);

        uint256 verificationGasLimit = mUserOp.verificationGasLimit;
        uint256 maxGasValues = mUserOp.preVerificationGas |
                    verificationGasLimit |
                        mUserOp.callGasLimit |
                        mUserOp.paymasterVerificationGasLimit |
                        mUserOp.paymasterPostOpGasLimit |
                        mUserOp.maxFeePerGas |
                        mUserOp.maxPriorityFeePerGas;
        require(maxGasValues <= type(uint120).max, FailedOp(opIndex, "AA94 gas values overflow"));

        uint256 requiredPreFund = _getRequiredPrefund(mUserOp);
        outOpInfo.prefund = requiredPreFund;
        validationData = _validateAccountPrepayment(
            opIndex,
            userOp,
            outOpInfo,
            requiredPreFund
        );

        require(
            _validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce),
            FailedOp(opIndex, "AA25 invalid account nonce")
        );

        unchecked {
            if (preGas - gasleft() > verificationGasLimit) {
                revert FailedOp(opIndex, "AA26 over verificationGasLimit");
            }
        }

        bytes memory context;
        if (mUserOp.paymaster != address(0)) {
            (context, paymasterValidationData) = _validatePaymasterPrepayment(
                opIndex,
                userOp,
                outOpInfo
            );
        }
        unchecked {
            outOpInfo.contextOffset = _getOffsetOfMemoryBytes(context);
            outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;
        }
    }

    function _postExecution(
        IPaymaster.PostOpMode mode,
        UserOpInfo memory opInfo,
        bytes memory context,
        uint256 actualGas
    ) internal virtual returns (uint256 actualGasCost) {
        uint256 preGas = gasleft();
        unchecked {
            address refundAddress;
            MemoryUserOp memory mUserOp = opInfo.mUserOp;
            uint256 gasPrice = _getUserOpGasPrice(mUserOp);

            address paymaster = mUserOp.paymaster;

            {
                uint256 executionGasUsed = actualGas - opInfo.preOpGas;

                actualGas += _getUnusedGasPenalty(executionGasUsed, mUserOp.callGasLimit);
            }
            uint256 postOpUnusedGasPenalty;
            if (paymaster == address(0)) {
                refundAddress = mUserOp.sender;
            } else {
                refundAddress = paymaster;
                if (context.length > 0) {
                    actualGasCost = actualGas * gasPrice;
                    uint256 postOpPreGas = gasleft();
                    if (mode != IPaymaster.PostOpMode.postOpReverted) {
                        try IPaymaster(paymaster).postOp{
                                gas: mUserOp.paymasterPostOpGasLimit
                            }(mode, context, actualGasCost, gasPrice)

                        {} catch {
                            bytes memory reason = Exec.getReturnData(REVERT_REASON_MAX_LEN);
                            revert PostOpReverted(reason);
                        }
                    }

                    uint256 postOpGasUsed = postOpPreGas - gasleft();
                    postOpUnusedGasPenalty = _getUnusedGasPenalty(postOpGasUsed, mUserOp.paymasterPostOpGasLimit);
                }
            }
            actualGas += preGas - gasleft() + postOpUnusedGasPenalty;
            actualGasCost = actualGas * gasPrice;
            uint256 prefund = opInfo.prefund;
            if (prefund < actualGasCost) {
                if (mode == IPaymaster.PostOpMode.postOpReverted) {
                    actualGasCost = prefund;
                    _emitPrefundTooLow(opInfo);
                    _emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);
                } else {
                    assembly ("memory-safe") {
                        mstore(0, INNER_REVERT_LOW_PREFUND)
                        revert(0, 32)
                    }
                }
            } else {
                uint256 refund = prefund - actualGasCost;
                _incrementDeposit(refundAddress, refund);
                bool success = mode == IPaymaster.PostOpMode.opSucceeded;
                _emitUserOperationEvent(opInfo, success, actualGasCost, actualGas);
            }
        }
    }

    function _getUserOpGasPrice(
        MemoryUserOp memory mUserOp
    ) internal view returns (uint256) {
        unchecked {
            uint256 maxFeePerGas = mUserOp.maxFeePerGas;
            uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;
            return min256(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
        }
    }

    function _getOffsetOfMemoryBytes(
        bytes memory data
    ) internal pure returns (uint256 offset) {
        assembly ("memory-safe") {
            offset := data
        }
    }

    function _getMemoryBytesFromOffset(
        uint256 offset
    ) internal pure returns (bytes memory result) {
        assembly ("memory-safe") {
            result := offset
        }
    }

    function _getFreePtr() internal pure returns (uint256 ptr) {
        assembly ("memory-safe") {
            ptr := mload(0x40)
        }
    }

    function _restoreFreePtr(uint256 ptr) internal pure {
        assembly ("memory-safe") {
            mstore(0x40, ptr)
        }
    }

    function _getUnusedGasPenalty(uint256 gasUsed, uint256 gasLimit) internal pure returns (uint256) {
        unchecked {
            if (gasLimit <= gasUsed + PENALTY_GAS_THRESHOLD) {
                return 0;
            }
            uint256 unusedGas = gasLimit - gasUsed;
            uint256 unusedGasPenalty = (unusedGas * UNUSED_GAS_PENALTY_PERCENT) / 100;
            return unusedGasPenalty;
        }
    }
}
</> Contract Creation Bytecode
0x610180604052604051610011906101a7565b604051809103905ff08015801561002a573d5f5f3e3d5ffd5b506001600160a01b031661016052348015610043575f5ffd5b5060408051808201825260078152664552433433333760c81b602080830191909152825180840190935260018352603160f81b908301529061008682600261012f565b6101205261009581600361012f565b61014052815160208084019190912060e052815190820120610100524660a05261012160e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c05261035e565b5f60208351101561014a5761014383610161565b905061015b565b81610155848261024c565b5060ff90505b92915050565b5f5f829050601f81511115610194578260405163305a27a960e01b815260040161018b9190610306565b60405180910390fd5b805161019f8261033b565b179392505050565b6105428061428183390190565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806101dc57607f821691505b6020821081036101fa57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561024757805f5260205f20601f840160051c810160208510156102255750805b601f840160051c820191505b81811015610244575f8155600101610231565b50505b505050565b81516001600160401b03811115610265576102656101b4565b6102798161027384546101c8565b84610200565b6020601f8211600181146102ab575f83156102945750848201515b5f19600385901b1c1916600184901b178455610244565b5f84815260208120601f198516915b828110156102da57878501518255602094850194600190920191016102ba565b50848210156102f757868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b805160208083015191908110156101fa575f1960209190910360031b1b16919050565b60805160a05160c05160e05161010051610120516101405161016051613eb36103ce5f395f81816101c901528181610e1501528181612ad30152612c1b01525f611e6401525f611e3701525f61184101525f61181901525f61177401525f61179e01525f6117c80152613eb35ff3fe608060405260043610610128575f3560e01c806335567e1a116100a8578063850aaf621161006d578063850aaf62146104b85780639b249f69146104d7578063b760faf9146104f6578063bb9fe6bf14610509578063c23a5cea1461051d578063dbed18e01461053c575f5ffd5b806335567e1a146102cc5780635287ce121461032a57806370a082311461043e578063765e827f1461047257806384b0196e14610491575f5ffd5b806313c65a6e116100ee57806313c65a6e14610212578063154e58dc146102265780631b2e01b814610258578063205c28781461028e57806322cdde4c146102ad575f5ffd5b806242dc531461013c57806301ffc9a71461016e5780630396cb601461019d57806309ccb880146101b05780630bd28e3b146101f3575f5ffd5b36610138576101363361055b565b005b5f5ffd5b348015610147575f5ffd5b5061015b61015636600461333b565b6105b4565b6040519081526020015b60405180910390f35b348015610179575f5ffd5b5061018d610188366004613487565b610748565b6040519015158152602001610165565b6101366101ab3660046134ae565b6107cf565b3480156101bb575f5ffd5b506040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152602001610165565b3480156101fe575f5ffd5b5061013661020d3660046134e7565b610a5a565b34801561021d575f5ffd5b5061015b610a90565b348015610231575f5ffd5b507f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e61015b565b348015610263575f5ffd5b5061015b610272366004613500565b600160209081525f928352604080842090915290825290205481565b348015610299575f5ffd5b506101366102a8366004613533565b610a9e565b3480156102b8575f5ffd5b5061015b6102c736600461355d565b610be9565b3480156102d7575f5ffd5b5061015b6102e6366004613500565b6001600160a01b0382165f9081526001602090815260408083206001600160c01b038516845290915290819020549082901b67ffffffffffffffff19161792915050565b348015610335575f5ffd5b506103e4610344366004613594565b6040805160a0810182525f80825260208201819052918101829052606081018290526080810191909152506001600160a01b03165f9081526020818152604091829020825160a0810184528154815260019091015460ff811615159282019290925261010082046001600160701b031692810192909252600160781b810463ffffffff166060830152600160981b900465ffffffffffff16608082015290565b60405161016591905f60a082019050825182526020830151151560208301526001600160701b03604084015116604083015263ffffffff606084015116606083015265ffffffffffff608084015116608083015292915050565b348015610449575f5ffd5b5061015b610458366004613594565b6001600160a01b03165f9081526020819052604090205490565b34801561047d575f5ffd5b5061013661048c3660046135ef565b610c31565b34801561049c575f5ffd5b506104a5610d3f565b604051610165979695949392919061366f565b3480156104c3575f5ffd5b506101366104d2366004613705565b610d81565b3480156104e2575f5ffd5b506101366104f1366004613755565b610dfc565b610136610504366004613594565b61055b565b348015610514575f5ffd5b50610136610eb1565b348015610528575f5ffd5b50610136610537366004613594565b610fdb565b348015610547575f5ffd5b506101366105563660046135ef565b611200565b6001600160a01b0381165f8181526020818152604091829020805434019081905591518281529192917f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c491015b60405180910390a25050565b5f5f5a905033301461060d5760405162461bcd60e51b815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c7900000000000000000060448201526064015b60405180910390fd5b8451606081015160a082015181016127100160405a603f028161063257610632613786565b0410156106485763deaddead60e01b5f5260205ffd5b87515f90156106ec575f610661845f01515f8c86611540565b9050806106ea575f61067260405190565b90505f610680610800611556565b8051909150156106da57855f01516001600160a01b03168b602001517f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a2018860200151846040516106d192919061379a565b60405180910390a35b6106e382604052565b6001935050505b505b5f88608001515a860301905061073a828a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250879250611587915050565b9a9950505050505050505050565b5f6001600160e01b0319821663349869f760e11b148061077857506001600160e01b03198216631313998b60e31b145b8061079357506001600160e01b0319821663cf28ef9760e01b145b806107ae57506001600160e01b03198216633e84f02160e01b145b806107c957506301ffc9a760e01b6001600160e01b03198316145b92915050565b335f90815260208190526040902063ffffffff82166108305760405162461bcd60e51b815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152606401610604565b600181015463ffffffff600160781b909104811690831610156108955760405162461bcd60e51b815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606401610604565b60018101545f906108b590349061010090046001600160701b03166137c6565b90505f81116108fb5760405162461bcd60e51b81526020600482015260126024820152711b9bc81cdd185ad9481cdc1958da599a595960721b6044820152606401610604565b6001600160701b038111156109435760405162461bcd60e51b815260206004820152600e60248201526d7374616b65206f766572666c6f7760901b6044820152606401610604565b6040805160a08101825283548152600160208083018281526001600160701b0386811685870190815263ffffffff8a8116606088018181525f60808a0181815233808352828a52918c90209a518b55965199909801805494519151965165ffffffffffff16600160981b0265ffffffffffff60981b1997909416600160781b029690961669ffffffffffffffffffff60781b1991909516610100026effffffffffffffffffffffffffff0019991515999099166effffffffffffffffffffffffffffff1990941693909317979097179190911691909117179055835185815290810192909252917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050565b335f9081526001602090815260408083206001600160c01b03851684529091528120805491610a88836137d9565b919050555050565b5f610a99611768565b905090565b335f908152602081905260409020805480831115610afe5760405162461bcd60e51b815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606401610604565b610b0883826137f1565b8255604080516001600160a01b03861681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb910160405180910390a25f846001600160a01b0316846040515f6040518083038185875af1925050503d805f8114610b97576040519150601f19603f3d011682016040523d82523d5f602084013e610b9c565b606091505b5050905080610be25760405162461bcd60e51b81526020600482015260126024820152716661696c656420746f20776974686472617760701b6044820152606401610604565b5050505050565b5f5f610bf483611891565b9050610c2a610c01610a90565b610c0b8584611937565b60405161190160f01b8152600281019290925260228201526042902090565b9392505050565b610c39611951565b815f816001600160401b03811115610c5357610c536131e8565b604051908082528060200260200182016040528015610c8c57816020015b610c79613161565b815260200190600190039081610c715790505b509050610c9c8585835f5f6119c0565b506040515f907fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972908290a15f5b83811015610d2457610d1881888884818110610ce757610ce7613804565b9050602002810190610cf99190613818565b858481518110610d0b57610d0b613804565b6020026020010151611a43565b90910190600101610cc9565b50610d2f8482611d11565b505050610d3a611e06565b505050565b5f6060805f5f5f6060610d50611e30565b610d58611e5d565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f5f846001600160a01b03168484604051610d9d929190613837565b5f60405180830381855af49150503d805f8114610dd5576040519150601f19603f3d011682016040523d82523d5f602084013e610dda565b606091505b50915091508181604051632650415560e21b8152600401610604929190613846565b604051632b870d1b60e11b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063570e1a3690610e4a908590600401613860565b6020604051808303815f875af1158015610e66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8a9190613872565b604051633653dc0360e11b81526001600160a01b0382166004820152909150602401610604565b335f90815260208190526040812060018101549091600160781b90910463ffffffff169003610f0f5760405162461bcd60e51b815260206004820152600a6024820152691b9bdd081cdd185ad95960b21b6044820152606401610604565b600181015460ff16610f575760405162461bcd60e51b8152602060048201526011602482015270616c726561647920756e7374616b696e6760781b6044820152606401610604565b60018101545f90610f7590600160781b900463ffffffff164261388d565b60018301805460ff65ffffffffffff60981b011916600160981b65ffffffffffff841690810260ff19169190911790915560405190815290915033907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a906020016105a8565b335f908152602081905260409020600181015461010090046001600160701b0316806110405760405162461bcd60e51b81526020600482015260146024820152734e6f207374616b6520746f20776974686472617760601b6044820152606401610604565b6001820154600160981b900465ffffffffffff166110a05760405162461bcd60e51b815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606401610604565b600182015442600160981b90910465ffffffffffff1611156111045760405162461bcd60e51b815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606401610604565b600182018054610100600160c81b0319169055604080516001600160a01b03851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a25f836001600160a01b0316826040515f6040518083038185875af1925050503d805f81146111a4576040519150601f19603f3d011682016040523d82523d5f602084013e6111a9565b606091505b50509050806111fa5760405162461bcd60e51b815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606401610604565b50505050565b611208611951565b815f805b82811015611343573686868381811061122757611227613804565b905060200281019061123991906138ab565b9050365f61124783806138bf565b90925090505f61125d6040850160208601613594565b9050806001600160a01b0381166001036112965760405163086a9f7560e41b81526001600160a01b039091166004820152602401610604565b506001600160a01b03811615611333576001600160a01b038116632dd8113384846112c46040890189613904565b6040518563ffffffff1660e01b81526004016112e39493929190613a8e565b5f604051808303815f87803b1580156112fa575f5ffd5b505af192505050801561130b575060015b6113335760405163086a9f7560e41b81526001600160a01b0382166004820152602401610604565b509390930192505060010161120c565b505f816001600160401b0381111561135d5761135d6131e8565b60405190808252806020026020018201604052801561139657816020015b611383613161565b81526020019060019003908161137b5790505b5090505f805b8481101561141057368888838181106113b7576113b7613804565b90506020028101906113c991906138ab565b9050365f6113d783806138bf565b90925090505f6113ed6040850160208601613594565b90506113fc838389848a6119c0565b9095019450506001909201915061139c9050565b506040517fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972905f90a1505f80805b85811015611528573689898381811061145957611459613804565b905060200281019061146b91906138ab565b905061147d6040820160208301613594565b6001600160a01b03167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d60405160405180910390a2365f6114be83806138bf565b9092509050805f5b8181101561151757611508888585848181106114e4576114e4613804565b90506020028101906114f69190613818565b8b8b81518110610d0b57610d0b613804565b600198890198970196016114c6565b50506001909301925061143e915050565b506115338682611d11565b5050505050610d3a611e06565b5f5f5f845160208601878987f195945050505050565b60603d821561156a578281111561156a5750815b604051602082018101604052818152815f602083013e9392505050565b5f5f5a85519091505f908161159b82611e8a565b90505f8260e0015190505f8960800151880390506115bd818560600151611ead565b90970196505f6001600160a01b0382166115da57835194506116ae565b8194505f895111156116ae5782880296505f5a905060028c600281111561160357611603613b19565b1461169557826001600160a01b0316637c627b218660a001518e8d8c896040518663ffffffff1660e01b815260040161163f9493929190613b2d565b5f604051808303815f88803b158015611656575f5ffd5b5087f193505050508015611668575060015b611695575f611678610800611556565b905080604051632b5e552f60e21b81526004016106049190613860565b5f5a820390506116a9818760a00151611ead565b925050505b805a8703018801975082880296505f8a604001519050878110156117115760028c60028111156116e0576116e0613b19565b03611702578097506116f18b611ecd565b6116fd8b5f8a8c611f1c565b611759565b63deadaa5160e01b5f5260205ffd5b6001600160a01b0386165f90815260208190526040812080548a840390810190915590808e600281111561174757611747613b19565b1490506117568d828c8e611f1c565b50505b50505050505050949350505050565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156117c057507f000000000000000000000000000000000000000000000000000000000000000046145b156117ea57507f000000000000000000000000000000000000000000000000000000000000000090565b610a99604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f36816118a16040850185613904565b915091506118af8282611f97565b6118bc57505f9392505050565b5f6118d26118cd6020870187613594565b611fc0565b905060148211611917576040516001600160601b0319606083901b1660208201526034015b604051602081830303815290604052805190602001209350505050919050565b806119258360148187613b74565b6040516020016118f793929190613b9b565b5f6119428383612089565b80519060200120905092915050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c1561199157604051633ee5aeb560e01b815260040160405180910390fd5b6119be60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90612182565b565b835f5b81811015611a39575f85828501815181106119e0576119e0613804565b602002602001015190505f5f611a1c8487018b8b87818110611a0457611a04613804565b9050602002810190611a169190613818565b85612189565b91509150611a2e84870183838a6123aa565b5050506001016119c3565b5095945050505050565b5f5f5a90505f611a54846060015190565b90505f5f611a6160405190565b9050365f611a7260608a018a613904565b9150915060605f826003811115611a8857843591505b506372288ed160e01b6001600160e01b0319821601611b35575f8b8b60200151604051602401611ab9929190613bc1565b60408051601f198184030181529181526020820180516001600160e01b0316638dd7712f60e01b1790525190915030906242dc5390611b009084908f908d90602401613c8c565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050925050611b8a565b306001600160a01b03166242dc5385858d8b604051602401611b5a9493929190613cc0565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505091505b60205f8351602085015f305af195505f519850611ba685604052565b505050505080611d07575f3d80602003611bc45760205f5f3e5f5191505b5063deaddead60e01b8103611c175787604051631101335b60e11b8152600401610604918152604060208201819052600f908201526e41413935206f7574206f662067617360881b606082015260800190565b63deadaa5160e01b8103611c66575f86608001515a611c3690876137f1565b611c4091906137c6565b6040880151909150611c5188611ecd565b611c5d885f8385611f1c565b9550611d059050565b5f611c7060405190565b875180516020808b01519201519293506001600160a01b0316917ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479290611cb7610800611556565b604051611cc592919061379a565b60405180910390a3611cd681604052565b5f87608001515a611ce790886137f1565b611cf191906137c6565b9050611d006002898784611587565b965050505b505b5050509392505050565b6001600160a01b038216611d675760405162461bcd60e51b815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152606401610604565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114611db0576040519150601f19603f3d011682016040523d82523d5f602084013e611db5565b606091505b5050905080610d3a5760405162461bcd60e51b815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152606401610604565b6119be5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f006119b8565b6060610a997f00000000000000000000000000000000000000000000000000000000000000006002612544565b6060610a997f00000000000000000000000000000000000000000000000000000000000000006003612544565b6101008101516101208201515f9190611ea5824883016125ed565b949350505050565b5f619c4083018211611ec057505f6107c9565b506064919003600a020490565b80518051602080840151928101516040519081526001600160a01b0390921692917f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e910160405180910390a350565b835160e081015181516020808801519301516040516001600160a01b039384169492909316927f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91611f899189908990899093845291151560208401526040830152606082015260800190565b60405180910390a450505050565b5f6002821015611fa857505f6107c9565b5050613b8160f11b90356001600160601b0319161490565b5f5f60175f5f853c505f516001600160e81b0319811661ef0160f01b14612077575f836001600160a01b03163b1161202f5760405162461bcd60e51b815260206004820152601260248201527173656e64657220686173206e6f20636f646560701b6044820152606401610604565b60405162461bcd60e51b815260206004820152601860248201527f6e6f7420616e204549502d373730322064656c656761746500000000000000006044820152606401610604565b60481c6001600160a01b031692915050565b60605f6120996020850185613594565b905060208401355f8481036120c2576120bd6120b86040880188613904565b612602565b6120c4565b845b90505f6120d76120b86060890189613904565b9050608087013560a088013560c08901355f6120f96120b860e08d018d613904565b604080517f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e60208201526001600160a01b039a909a168a82015260608a019890985260808901969096525060a087019390935260c086019190915260e0850152610100840152610120808401919091528151808403909101815261014090920190529392505050565b80825d5050565b5f5f5f5a845190915061219c8682612614565b5f6121a660405190565b90506121b187610be9565b60208701526121bf81604052565b604082015161012083015161010084015160a08501516080860151606087015160c088015186171717171717896effffffffffffffffffffffffffffff8211156122535760408051631101335b60e11b815260048101929092526024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152608401610604565b505f6122828560c081015160a08201516080830151606084015160408501516101009095015194010101010290565b60408a0181905290506122978b8b8b84612758565b97506122aa855f0151866020015161283f565b8b906123005760408051631101335b60e11b815260048101929092526024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152608401610604565b50825a8703111561235d578a604051631101335b60e11b8152600401610604918152604060208201819052601e908201527f41413236206f76657220766572696669636174696f6e4761734c696d69740000606082015260800190565b60e08501516060906001600160a01b0316156123835761237e8c8c8c61288b565b985090505b8060608b015260a08b01355a8803018a608001818152505050505050505050935093915050565b5f5f6123b58561298f565b91509150816001600160a01b0316836001600160a01b03161461241b5785604051631101335b60e11b81526004016106049181526040602082018190526014908201527320a0991a1039b4b3b730ba3ab9329032b93937b960611b606082015260800190565b80156124735785604051631101335b60e11b81526004016106049181526040602082018190526017908201527f414132322065787069726564206f72206e6f7420647565000000000000000000606082015260800190565b5f61247d8561298f565b925090506001600160a01b038116156124d95786604051631101335b60e11b81526004016106049181526040602082018190526014908201527320a0999a1039b4b3b730ba3ab9329032b93937b960611b606082015260800190565b811561253b5786604051631101335b60e11b81526004016106049181526040602082018190526021908201527f41413332207061796d61737465722065787069726564206f72206e6f742064756060820152606560f81b608082015260a00190565b50505050505050565b606060ff831461255e57612557836129df565b90506107c9565b81805461256a90613cf5565b80601f016020809104026020016040519081016040528092919081815260200182805461259690613cf5565b80156125e15780601f106125b8576101008083540402835291602001916125e1565b820191905f5260205f20905b8154815290600101906020018083116125c457829003601f168201915b505050505090506107c9565b5f8183106125fb5781610c2a565b5090919050565b5f604051828085833790209392505050565b6126216020830183613594565b6001600160a01b03168152602080830135908201526126436080830135612a1c565b6060830152604082015260a082013560c08083019190915261266790830135612a1c565b610100830152610120820152365f61268260e0850185613904565b909250905080156111fa5760348110156126de5760405162461bcd60e51b815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606401610604565b5f6126e98383612a3b565b60a0870152608086015290506001600160a01b0381166127445760405162461bcd60e51b815260206004820152601660248201527520a09c9c1034b73b30b634b2103830bcb6b0b9ba32b960511b6044820152606401610604565b6001600160a01b031660e084015250505050565b815180515f9190612776878661277160408a018a613904565b612aa2565b60e08201515f6001600160a01b0382166127b7576001600160a01b0383165f908152602081905260409020548681116127b1578087036127b3565b5f5b9150505b6127c389898984612e67565b94506001600160a01b038216612833576127dd8387612f89565b6128335788604051631101335b60e11b81526004016106049181526040602082018190526017908201527f41413231206469646e2774207061792070726566756e64000000000000000000606082015260800190565b50505050949350505050565b6001600160a01b0382165f90815260016020908152604080832084821c80855292528220805484916001600160401b03831691908561287d836137d9565b909155501495945050505050565b60605f5f5a845160e0810151604087015192935090916128ab8282612f89565b6129015788604051631101335b60e11b8152600401610604918152604060208201819052601e908201527f41413331207061796d6173746572206465706f73697420746f6f206c6f770000606082015260800190565b60808301516129118a8a8a612fc2565b9097509550805a860311156129825789604051631101335b60e11b81526004016106049181526040602082018190526027908201527f41413336206f766572207061796d6173746572566572696669636174696f6e47606082015266185cd31a5b5a5d60ca1b608082015260a00190565b5050505050935093915050565b5f5f825f036129a257505f928392509050565b5f6129ac846130cb565b9050806040015165ffffffffffff164211806129d45750806020015165ffffffffffff164211155b905194909350915050565b60605f6129eb8361313a565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f5f612a288360801c90565b6001600160801b03841691509150915091565b5f8080612a4b6014828688613b74565b612a5491613d2d565b60601c612a65602460148789613b74565b612a6e91613d6b565b60801c612a7f60346024888a613b74565b612a8891613d6b565b9194506001600160801b0316925060801c90509250925092565b80156111fa57825151612ab58383611f97565b15612b5b576014821115612b55578351604001516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c09ad0d99083612b08866014818a613b74565b6040518563ffffffff1660e01b8152600401612b2693929190613da1565b5f604051808303815f88803b158015612b3d575f5ffd5b5087f1158015612b4f573d5f5f3e3d5ffd5b50505050505b506111fa565b6001600160a01b0381163b15612bbd5784604051631101335b60e11b8152600401610604918152604060208201819052601f908201527f414131302073656e64657220616c726561647920636f6e737472756374656400606082015260800190565b6014821015612c185784604051631101335b60e11b81526004016106049181526040602082018190526017908201527f4141393920696e6974436f646520746f6f20736d616c6c000000000000000000606082015260800190565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663570e1a36865f01516040015186866040518463ffffffff1660e01b8152600401612c6f929190613dce565b6020604051808303815f8887f1158015612c8b573d5f5f3e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190612cb09190613872565b90506001600160a01b038116612d125785604051631101335b60e11b8152600401610604918152604060208201819052601b908201527f4141313320696e6974436f6465206661696c6564206f72204f4f470000000000606082015260800190565b816001600160a01b0316816001600160a01b031614612d7c5785604051631101335b60e11b815260040161060491815260406020808301829052908201527f4141313420696e6974436f6465206d7573742072657475726e2073656e646572606082015260800190565b806001600160a01b03163b5f03612dde5785604051631101335b60e11b815260040161060491815260406020808301829052908201527f4141313520696e6974436f6465206d757374206372656174652073656e646572606082015260800190565b5f612dec6014828688613b74565b612df591613d2d565b60601c9050826001600160a01b031686602001517fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d83895f015160e00151604051612e569291906001600160a01b0392831681529116602082015260400190565b60405180910390a350505050505050565b8151604081015190515f91908280612e7e60405190565b90505f88886020015188604051602401612e9a93929190613de1565b60408051601f19818403018152919052602080820180516001600160e01b03166306608bdf60e21b178152825192935090915f9182888af192505f51955060203d14612ee4575f92505b612eed82604052565b505080612f7e57816001600160a01b03163b5f03612f575787604051631101335b60e11b81526004016106049181526040602082018190526019908201527f41413230206163636f756e74206e6f74206465706c6f79656400000000000000606082015260800190565b87612f63610800611556565b6040516365c8fd4d60e01b8152600401610604929190613e05565b505050949350505050565b6001600160a01b0382165f908152602081905260408120805483811015612fb4575f925050506107c9565b839003905550600192915050565b60605f5f612fcf60405190565b90505f8585602001518660400151604051602401612fef93929190613de1565b60408051601f198184030181529190526020810180516001600160e01b03166314add44b60e21b178152865160e08101516080909101518351939450909290915f9182918291829182918291829190828b8bf194503d9050805f8a3e6020890151995088519250606081039150604089019a508a519350841580613074575082604014155b8061308157508184601f01105b156130ad578d613092610800611556565b6040516365c8fd4d60e01b8152600401610604929190613e41565b601f8101601f19168901604052505050505050505050935093915050565b604080516060810182525f80825260208201819052918101919091528160a081901c65ffffffffffff81165f03613105575065ffffffffffff5b604080516060810182526001600160a01b03909316835260d09490941c602083015265ffffffffffff16928101929092525090565b5f60ff8216601f8111156107c957604051632cd44ac360e21b815260040160405180910390fd5b6040518060a001604052806131ca6040518061014001604052805f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81526020015f81525090565b81526020015f81526020015f81526020015f81526020015f81525090565b634e487b7160e01b5f52604160045260245ffd5b60405160a081016001600160401b038111828210171561321e5761321e6131e8565b60405290565b60405161014081016001600160401b038111828210171561321e5761321e6131e8565b5f82601f830112613256575f5ffd5b81356001600160401b0381111561326f5761326f6131e8565b604051601f8201601f19908116603f011681016001600160401b038111828210171561329d5761329d6131e8565b6040528181528382016020018510156132b4575f5ffd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b03811681146132e4575f5ffd5b50565b80356132f2816132d0565b919050565b5f5f83601f840112613307575f5ffd5b5081356001600160401b0381111561331d575f5ffd5b602083019150836020828501011115613334575f5ffd5b9250929050565b5f5f5f5f848603610200811215613350575f5ffd5b85356001600160401b03811115613365575f5ffd5b61337188828901613247565b955050601f19016101c0811215613386575f5ffd5b61338e6131fc565b61014082121561339c575f5ffd5b6133a4613224565b91506133b2602088016132e7565b82526040878101356020840152606080890135918401919091526080808901359184019190915260a0808901359184019190915260c0808901359184019190915260e08801359083015261340961010088016132e7565b60e08301526101208781013561010084015261014088013590830152908152610160860135602082015261018086013560408201526101a086013560608201526101c0860135608082015292506101e08501356001600160401b0381111561346f575f5ffd5b61347b878288016132f7565b95989497509550505050565b5f60208284031215613497575f5ffd5b81356001600160e01b031981168114610c2a575f5ffd5b5f602082840312156134be575f5ffd5b813563ffffffff81168114610c2a575f5ffd5b80356001600160c01b03811681146132f2575f5ffd5b5f602082840312156134f7575f5ffd5b610c2a826134d1565b5f5f60408385031215613511575f5ffd5b823561351c816132d0565b915061352a602084016134d1565b90509250929050565b5f5f60408385031215613544575f5ffd5b823561354f816132d0565b946020939093013593505050565b5f6020828403121561356d575f5ffd5b81356001600160401b03811115613582575f5ffd5b82016101208185031215610c2a575f5ffd5b5f602082840312156135a4575f5ffd5b8135610c2a816132d0565b5f5f83601f8401126135bf575f5ffd5b5081356001600160401b038111156135d5575f5ffd5b6020830191508360208260051b8501011115613334575f5ffd5b5f5f5f60408486031215613601575f5ffd5b83356001600160401b03811115613616575f5ffd5b613622868287016135af565b9094509250506020840135613636816132d0565b809150509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f61368d60e0830189613641565b828103604084015261369f8189613641565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b818110156136f45783518352602093840193909201916001016136d6565b50909b9a5050505050505050505050565b5f5f5f60408486031215613717575f5ffd5b8335613722816132d0565b925060208401356001600160401b0381111561373c575f5ffd5b613748868287016132f7565b9497909650939450505050565b5f60208284031215613765575f5ffd5b81356001600160401b0381111561377a575f5ffd5b611ea584828501613247565b634e487b7160e01b5f52601260045260245ffd5b828152604060208201525f611ea56040830184613641565b634e487b7160e01b5f52601160045260245ffd5b808201808211156107c9576107c96137b2565b5f600182016137ea576137ea6137b2565b5060010190565b818103818111156107c9576107c96137b2565b634e487b7160e01b5f52603260045260245ffd5b5f823561011e1983360301811261382d575f5ffd5b9190910192915050565b818382375f9101908152919050565b8215158152604060208201525f611ea56040830184613641565b602081525f610c2a6020830184613641565b5f60208284031215613882575f5ffd5b8151610c2a816132d0565b65ffffffffffff81811683821601908111156107c9576107c96137b2565b5f8235605e1983360301811261382d575f5ffd5b5f5f8335601e198436030181126138d4575f5ffd5b8301803591506001600160401b038211156138ed575f5ffd5b6020019150600581901b3603821315613334575f5ffd5b5f5f8335601e19843603018112613919575f5ffd5b8301803591506001600160401b03821115613932575f5ffd5b602001915036819003821315613334575f5ffd5b5f5f8335601e1984360301811261395b575f5ffd5b83016020810192503590506001600160401b03811115613979575f5ffd5b803603821315613334575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6139c9826139bc836132e7565b6001600160a01b03169052565b602081810135908301525f6139e16040830183613946565b61012060408601526139f861012086018284613987565b915050613a086060840184613946565b8583036060870152613a1b838284613987565b6080868101359088015260a0808701359088015260c080870135908801529250613a4b91505060e0840184613946565b85830360e0870152613a5e838284613987565b92505050613a70610100840184613946565b858303610100870152613a84838284613987565b9695505050505050565b604080825281018490525f6060600586901b83018101908301878361011e1936839003015b89821015613af757868503605f190184528235818112613ad1575f5ffd5b613add868d83016139af565b955050602083019250602084019350600182019150613ab3565b505050508281036020840152613b0e818587613987565b979650505050505050565b634e487b7160e01b5f52602160045260245ffd5b5f60038610613b4a57634e487b7160e01b5f52602160045260245ffd5b85825260806020830152613b616080830186613641565b6040830194909452506060015292915050565b5f5f85851115613b82575f5ffd5b83861115613b8e575f5ffd5b5050820193919092039150565b6001600160601b03198460601b168152818360148301375f910160140190815292915050565b604081525f613bd360408301856139af565b90508260208301529392505050565b805180516001600160a01b031683526020810151602084015260408101516040840152606081015160608401526080810151608084015260a081015160a084015260c081015160c084015260e0810151613c4760e08501826001600160a01b03169052565b5061010081810151908401526101209081015190830152602081015161014083015260408101516101608301526060810151610180830152608001516101a090910152565b61020081525f613ca0610200830186613641565b613cad6020840186613be2565b8281036101e0840152613a848185613641565b61020081525f613cd561020083018688613987565b613ce26020840186613be2565b8281036101e0840152613b0e8185613641565b600181811c90821680613d0957607f821691505b602082108103613d2757634e487b7160e01b5f52602260045260245ffd5b50919050565b80356001600160601b03198116906014841015613d64576001600160601b03196001600160601b03198560140360031b1b82161691505b5092915050565b80356001600160801b03198116906010841015613d64576001600160801b031960109490940360031b84901b1690921692915050565b6001600160a01b03841681526040602082018190525f90613dc59083018486613987565b95945050505050565b602081525f611ea5602083018486613987565b606081525f613df360608301866139af565b60208301949094525060400152919050565b82815260606020820152600d60608201526c10504c8cc81c995d995c9d1959609a1b608082015260a060408201525f611ea560a0830184613641565b82815260606020820152600d60608201526c10504cccc81c995d995c9d1959609a1b608082015260a060408201525f611ea560a083018461364156fea2646970667358221220740811fa439297b941d35bd6f03090191190666139feccfe49c6930a75cfe6ec64736f6c634300081e003360a0604052348015600e575f5ffd5b503360805260805161050b6100375f395f818160770152818160ba01526101bc015261050b5ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c8063570e1a3614610043578063b0d691fe14610072578063c09ad0d914610099575b5f5ffd5b61005661005136600461029e565b6100ae565b6040516001600160a01b03909116815260200160405180910390f35b6100567f000000000000000000000000000000000000000000000000000000000000000081565b6100ac6100a7366004610320565b6101b1565b005b5f336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461012c5760405162461bcd60e51b815260206004820181905260248201527f414139372073686f756c642063616c6c2066726f6d20456e747279506f696e7460448201526064015b60405180910390fd5b5f61013a60148285876103f1565b61014391610418565b60601c90505f61015684601481886103f1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525084519495509360209350849250905082850182875af1905080156101a8575f5193505b50505092915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146102295760405162461bcd60e51b815260206004820181905260248201527f414139372073686f756c642063616c6c2066726f6d20456e747279506f696e746044820152606401610123565b5f5f5f8351602085015f875af1905080610268575f61024961080061026d565b90505f816040516365c8fd4d60e01b8152600401610123929190610465565b505050565b60603d821561028157828111156102815750815b604051602082018101604052818152815f602083013e9392505050565b5f5f602083850312156102af575f5ffd5b823567ffffffffffffffff8111156102c5575f5ffd5b8301601f810185136102d5575f5ffd5b803567ffffffffffffffff8111156102eb575f5ffd5b8560208284010111156102fc575f5ffd5b6020919091019590945092505050565b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610331575f5ffd5b82356001600160a01b0381168114610347575f5ffd5b9150602083013567ffffffffffffffff811115610362575f5ffd5b8301601f81018513610372575f5ffd5b803567ffffffffffffffff81111561038c5761038c61030c565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156103bb576103bb61030c565b6040528181528282016020018710156103d2575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f5f858511156103ff575f5ffd5b8386111561040b575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561045e576bffffffffffffffffffffffff196bffffffffffffffffffffffff198560140360031b1b82161691505b5092915050565b82815260606020820152601f60608201527f4141313320454950373730322073656e64657220696e6974206661696c656400608082015260a060408201525f82518060a0840152806020850160c085015e5f60c0828501015260c0601f19601f830116840101915050939250505056fea26469706673582212206dcc30393d64ce7cd328e54cf3999a153b0c0dbaafe96d7e353c69f367f7c9b264736f6c634300081e0033
</> Contract ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"ret","type":"bytes"}],"name":"DelegateAndRevert","type":"error"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"FailedOp","type":"error"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"inner","type":"bytes"}],"name":"FailedOpWithRevert","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"name":"PostOpReverted","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderAddressResult","type":"error"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureValidationFailed","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"factory","type":"address"},{"indexed":false,"internalType":"address","name":"paymaster","type":"address"}],"name":"AccountDeployed","type":"event"},{"anonymous":false,"inputs":[],"name":"BeforeExecution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalDeposit","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"revertReason","type":"bytes"}],"name":"PostOpRevertReason","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureAggregatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalStaked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawTime","type":"uint256"}],"name":"StakeUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"paymaster","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint256","name":"actualGasCost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualGasUsed","type":"uint256"}],"name":"UserOperationEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"UserOperationPrefundTooLow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"revertReason","type":"bytes"}],"name":"UserOperationRevertReason","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"}],"name":"addStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"delegateAndRevert","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"depositTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getDepositInfo","outputs":[{"components":[{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"bool","name":"staked","type":"bool"},{"internalType":"uint112","name":"stake","type":"uint112"},{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"},{"internalType":"uint48","name":"withdrawTime","type":"uint48"}],"internalType":"struct IStakeManager.DepositInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparatorV4","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint192","name":"key","type":"uint192"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPackedUserOpTypeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"getSenderAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"userOp","type":"tuple"}],"name":"getUserOpHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"userOps","type":"tuple[]"},{"internalType":"contract IAggregator","name":"aggregator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IEntryPoint.UserOpsPerAggregator[]","name":"opsPerAggregator","type":"tuple[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleAggregatedOps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"ops","type":"tuple[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleOps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"key","type":"uint192"}],"name":"incrementNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"callData","type":"bytes"},{"components":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterVerificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterPostOpGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"address","name":"paymaster","type":"address"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"}],"internalType":"struct EntryPoint.MemoryUserOp","name":"mUserOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"uint256","name":"contextOffset","type":"uint256"},{"internalType":"uint256","name":"preOpGas","type":"uint256"}],"internalType":"struct EntryPoint.UserOpInfo","name":"opInfo","type":"tuple"},{"internalType":"bytes","name":"context","type":"bytes"}],"name":"innerHandleOp","outputs":[{"internalType":"uint256","name":"actualGasCost","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint192","name":"","type":"uint192"}],"name":"nonceSequenceNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"senderCreator","outputs":[{"internalType":"contract ISenderCreator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"}],"name":"withdrawStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"},{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
</> Contract Deployment Bytecode
0x608060405260043610610128575f3560e01c806335567e1a116100a8578063850aaf621161006d578063850aaf62146104b85780639b249f69146104d7578063b760faf9146104f6578063bb9fe6bf14610509578063c23a5cea1461051d578063dbed18e01461053c575f5ffd5b806335567e1a146102cc5780635287ce121461032a57806370a082311461043e578063765e827f1461047257806384b0196e14610491575f5ffd5b806313c65a6e116100ee57806313c65a6e14610212578063154e58dc146102265780631b2e01b814610258578063205c28781461028e57806322cdde4c146102ad575f5ffd5b806242dc531461013c57806301ffc9a71461016e5780630396cb601461019d57806309ccb880146101b05780630bd28e3b146101f3575f5ffd5b36610138576101363361055b565b005b5f5ffd5b348015610147575f5ffd5b5061015b61015636600461333b565b6105b4565b6040519081526020015b60405180910390f35b348015610179575f5ffd5b5061018d610188366004613487565b610748565b6040519015158152602001610165565b6101366101ab3660046134ae565b6107cf565b3480156101bb575f5ffd5b506040516001600160a01b037f000000000000000000000000bbd9cebbb6565bf6f35c5ee8abaa6cebfd8a07ff168152602001610165565b3480156101fe575f5ffd5b5061013661020d3660046134e7565b610a5a565b34801561021d575f5ffd5b5061015b610a90565b348015610231575f5ffd5b507f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e61015b565b348015610263575f5ffd5b5061015b610272366004613500565b600160209081525f928352604080842090915290825290205481565b348015610299575f5ffd5b506101366102a8366004613533565b610a9e565b3480156102b8575f5ffd5b5061015b6102c736600461355d565b610be9565b3480156102d7575f5ffd5b5061015b6102e6366004613500565b6001600160a01b0382165f9081526001602090815260408083206001600160c01b038516845290915290819020549082901b67ffffffffffffffff19161792915050565b348015610335575f5ffd5b506103e4610344366004613594565b6040805160a0810182525f80825260208201819052918101829052606081018290526080810191909152506001600160a01b03165f9081526020818152604091829020825160a0810184528154815260019091015460ff811615159282019290925261010082046001600160701b031692810192909252600160781b810463ffffffff166060830152600160981b900465ffffffffffff16608082015290565b60405161016591905f60a082019050825182526020830151151560208301526001600160701b03604084015116604083015263ffffffff606084015116606083015265ffffffffffff608084015116608083015292915050565b348015610449575f5ffd5b5061015b610458366004613594565b6001600160a01b03165f9081526020819052604090205490565b34801561047d575f5ffd5b5061013661048c3660046135ef565b610c31565b34801561049c575f5ffd5b506104a5610d3f565b604051610165979695949392919061366f565b3480156104c3575f5ffd5b506101366104d2366004613705565b610d81565b3480156104e2575f5ffd5b506101366104f1366004613755565b610dfc565b610136610504366004613594565b61055b565b348015610514575f5ffd5b50610136610eb1565b348015610528575f5ffd5b50610136610537366004613594565b610fdb565b348015610547575f5ffd5b506101366105563660046135ef565b611200565b6001600160a01b0381165f8181526020818152604091829020805434019081905591518281529192917f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c491015b60405180910390a25050565b5f5f5a905033301461060d5760405162461bcd60e51b815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c7900000000000000000060448201526064015b60405180910390fd5b8451606081015160a082015181016127100160405a603f028161063257610632613786565b0410156106485763deaddead60e01b5f5260205ffd5b87515f90156106ec575f610661845f01515f8c86611540565b9050806106ea575f61067260405190565b90505f610680610800611556565b8051909150156106da57855f01516001600160a01b03168b602001517f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a2018860200151846040516106d192919061379a565b60405180910390a35b6106e382604052565b6001935050505b505b5f88608001515a860301905061073a828a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250879250611587915050565b9a9950505050505050505050565b5f6001600160e01b0319821663349869f760e11b148061077857506001600160e01b03198216631313998b60e31b145b8061079357506001600160e01b0319821663cf28ef9760e01b145b806107ae57506001600160e01b03198216633e84f02160e01b145b806107c957506301ffc9a760e01b6001600160e01b03198316145b92915050565b335f90815260208190526040902063ffffffff82166108305760405162461bcd60e51b815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152606401610604565b600181015463ffffffff600160781b909104811690831610156108955760405162461bcd60e51b815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606401610604565b60018101545f906108b590349061010090046001600160701b03166137c6565b90505f81116108fb5760405162461bcd60e51b81526020600482015260126024820152711b9bc81cdd185ad9481cdc1958da599a595960721b6044820152606401610604565b6001600160701b038111156109435760405162461bcd60e51b815260206004820152600e60248201526d7374616b65206f766572666c6f7760901b6044820152606401610604565b6040805160a08101825283548152600160208083018281526001600160701b0386811685870190815263ffffffff8a8116606088018181525f60808a0181815233808352828a52918c90209a518b55965199909801805494519151965165ffffffffffff16600160981b0265ffffffffffff60981b1997909416600160781b029690961669ffffffffffffffffffff60781b1991909516610100026effffffffffffffffffffffffffff0019991515999099166effffffffffffffffffffffffffffff1990941693909317979097179190911691909117179055835185815290810192909252917fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01910160405180910390a2505050565b335f9081526001602090815260408083206001600160c01b03851684529091528120805491610a88836137d9565b919050555050565b5f610a99611768565b905090565b335f908152602081905260409020805480831115610afe5760405162461bcd60e51b815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606401610604565b610b0883826137f1565b8255604080516001600160a01b03861681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb910160405180910390a25f846001600160a01b0316846040515f6040518083038185875af1925050503d805f8114610b97576040519150601f19603f3d011682016040523d82523d5f602084013e610b9c565b606091505b5050905080610be25760405162461bcd60e51b81526020600482015260126024820152716661696c656420746f20776974686472617760701b6044820152606401610604565b5050505050565b5f5f610bf483611891565b9050610c2a610c01610a90565b610c0b8584611937565b60405161190160f01b8152600281019290925260228201526042902090565b9392505050565b610c39611951565b815f816001600160401b03811115610c5357610c536131e8565b604051908082528060200260200182016040528015610c8c57816020015b610c79613161565b815260200190600190039081610c715790505b509050610c9c8585835f5f6119c0565b506040515f907fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972908290a15f5b83811015610d2457610d1881888884818110610ce757610ce7613804565b9050602002810190610cf99190613818565b858481518110610d0b57610d0b613804565b6020026020010151611a43565b90910190600101610cc9565b50610d2f8482611d11565b505050610d3a611e06565b505050565b5f6060805f5f5f6060610d50611e30565b610d58611e5d565b604080515f80825260208201909252600f60f81b9b939a50919850469750309650945092509050565b5f5f846001600160a01b03168484604051610d9d929190613837565b5f60405180830381855af49150503d805f8114610dd5576040519150601f19603f3d011682016040523d82523d5f602084013e610dda565b606091505b50915091508181604051632650415560e21b8152600401610604929190613846565b604051632b870d1b60e11b81525f906001600160a01b037f000000000000000000000000bbd9cebbb6565bf6f35c5ee8abaa6cebfd8a07ff169063570e1a3690610e4a908590600401613860565b6020604051808303815f875af1158015610e66573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8a9190613872565b604051633653dc0360e11b81526001600160a01b0382166004820152909150602401610604565b335f90815260208190526040812060018101549091600160781b90910463ffffffff169003610f0f5760405162461bcd60e51b815260206004820152600a6024820152691b9bdd081cdd185ad95960b21b6044820152606401610604565b600181015460ff16610f575760405162461bcd60e51b8152602060048201526011602482015270616c726561647920756e7374616b696e6760781b6044820152606401610604565b60018101545f90610f7590600160781b900463ffffffff164261388d565b60018301805460ff65ffffffffffff60981b011916600160981b65ffffffffffff841690810260ff19169190911790915560405190815290915033907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a906020016105a8565b335f908152602081905260409020600181015461010090046001600160701b0316806110405760405162461bcd60e51b81526020600482015260146024820152734e6f207374616b6520746f20776974686472617760601b6044820152606401610604565b6001820154600160981b900465ffffffffffff166110a05760405162461bcd60e51b815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606401610604565b600182015442600160981b90910465ffffffffffff1611156111045760405162461bcd60e51b815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606401610604565b600182018054610100600160c81b0319169055604080516001600160a01b03851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a25f836001600160a01b0316826040515f6040518083038185875af1925050503d805f81146111a4576040519150601f19603f3d011682016040523d82523d5f602084013e6111a9565b606091505b50509050806111fa5760405162461bcd60e51b815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606401610604565b50505050565b611208611951565b815f805b82811015611343573686868381811061122757611227613804565b905060200281019061123991906138ab565b9050365f61124783806138bf565b90925090505f61125d6040850160208601613594565b9050806001600160a01b0381166001036112965760405163086a9f7560e41b81526001600160a01b039091166004820152602401610604565b506001600160a01b03811615611333576001600160a01b038116632dd8113384846112c46040890189613904565b6040518563ffffffff1660e01b81526004016112e39493929190613a8e565b5f604051808303815f87803b1580156112fa575f5ffd5b505af192505050801561130b575060015b6113335760405163086a9f7560e41b81526001600160a01b0382166004820152602401610604565b509390930192505060010161120c565b505f816001600160401b0381111561135d5761135d6131e8565b60405190808252806020026020018201604052801561139657816020015b611383613161565b81526020019060019003908161137b5790505b5090505f805b8481101561141057368888838181106113b7576113b7613804565b90506020028101906113c991906138ab565b9050365f6113d783806138bf565b90925090505f6113ed6040850160208601613594565b90506113fc838389848a6119c0565b9095019450506001909201915061139c9050565b506040517fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972905f90a1505f80805b85811015611528573689898381811061145957611459613804565b905060200281019061146b91906138ab565b905061147d6040820160208301613594565b6001600160a01b03167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d60405160405180910390a2365f6114be83806138bf565b9092509050805f5b8181101561151757611508888585848181106114e4576114e4613804565b90506020028101906114f69190613818565b8b8b81518110610d0b57610d0b613804565b600198890198970196016114c6565b50506001909301925061143e915050565b506115338682611d11565b5050505050610d3a611e06565b5f5f5f845160208601878987f195945050505050565b60603d821561156a578281111561156a5750815b604051602082018101604052818152815f602083013e9392505050565b5f5f5a85519091505f908161159b82611e8a565b90505f8260e0015190505f8960800151880390506115bd818560600151611ead565b90970196505f6001600160a01b0382166115da57835194506116ae565b8194505f895111156116ae5782880296505f5a905060028c600281111561160357611603613b19565b1461169557826001600160a01b0316637c627b218660a001518e8d8c896040518663ffffffff1660e01b815260040161163f9493929190613b2d565b5f604051808303815f88803b158015611656575f5ffd5b5087f193505050508015611668575060015b611695575f611678610800611556565b905080604051632b5e552f60e21b81526004016106049190613860565b5f5a820390506116a9818760a00151611ead565b925050505b805a8703018801975082880296505f8a604001519050878110156117115760028c60028111156116e0576116e0613b19565b03611702578097506116f18b611ecd565b6116fd8b5f8a8c611f1c565b611759565b63deadaa5160e01b5f5260205ffd5b6001600160a01b0386165f90815260208190526040812080548a840390810190915590808e600281111561174757611747613b19565b1490506117568d828c8e611f1c565b50505b50505050505050949350505050565b5f306001600160a01b037f000000000000000000000000119c4192aa136d68c310de01c3ad1993e9511c75161480156117c057507f000000000000000000000000000000000000000000000000000000000000005546145b156117ea57507f97139439794968df6c4e36884a0dbc461ff1bd2fe82ff212e7111b803aad1d0f90565b610a99604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f364da28a5c92bcc87fe97c8813a6c6b8a3a049b0ea0a328fcb0b4f0e00337586918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f36816118a16040850185613904565b915091506118af8282611f97565b6118bc57505f9392505050565b5f6118d26118cd6020870187613594565b611fc0565b905060148211611917576040516001600160601b0319606083901b1660208201526034015b604051602081830303815290604052805190602001209350505050919050565b806119258360148187613b74565b6040516020016118f793929190613b9b565b5f6119428383612089565b80519060200120905092915050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c1561199157604051633ee5aeb560e01b815260040160405180910390fd5b6119be60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90612182565b565b835f5b81811015611a39575f85828501815181106119e0576119e0613804565b602002602001015190505f5f611a1c8487018b8b87818110611a0457611a04613804565b9050602002810190611a169190613818565b85612189565b91509150611a2e84870183838a6123aa565b5050506001016119c3565b5095945050505050565b5f5f5a90505f611a54846060015190565b90505f5f611a6160405190565b9050365f611a7260608a018a613904565b9150915060605f826003811115611a8857843591505b506372288ed160e01b6001600160e01b0319821601611b35575f8b8b60200151604051602401611ab9929190613bc1565b60408051601f198184030181529181526020820180516001600160e01b0316638dd7712f60e01b1790525190915030906242dc5390611b009084908f908d90602401613c8c565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050925050611b8a565b306001600160a01b03166242dc5385858d8b604051602401611b5a9493929190613cc0565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505091505b60205f8351602085015f305af195505f519850611ba685604052565b505050505080611d07575f3d80602003611bc45760205f5f3e5f5191505b5063deaddead60e01b8103611c175787604051631101335b60e11b8152600401610604918152604060208201819052600f908201526e41413935206f7574206f662067617360881b606082015260800190565b63deadaa5160e01b8103611c66575f86608001515a611c3690876137f1565b611c4091906137c6565b6040880151909150611c5188611ecd565b611c5d885f8385611f1c565b9550611d059050565b5f611c7060405190565b875180516020808b01519201519293506001600160a01b0316917ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479290611cb7610800611556565b604051611cc592919061379a565b60405180910390a3611cd681604052565b5f87608001515a611ce790886137f1565b611cf191906137c6565b9050611d006002898784611587565b965050505b505b5050509392505050565b6001600160a01b038216611d675760405162461bcd60e51b815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152606401610604565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114611db0576040519150601f19603f3d011682016040523d82523d5f602084013e611db5565b606091505b5050905080610d3a5760405162461bcd60e51b815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152606401610604565b6119be5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f006119b8565b6060610a997f45524334333337000000000000000000000000000000000000000000000000076002612544565b6060610a997f31000000000000000000000000000000000000000000000000000000000000016003612544565b6101008101516101208201515f9190611ea5824883016125ed565b949350505050565b5f619c4083018211611ec057505f6107c9565b506064919003600a020490565b80518051602080840151928101516040519081526001600160a01b0390921692917f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e910160405180910390a350565b835160e081015181516020808801519301516040516001600160a01b039384169492909316927f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91611f899189908990899093845291151560208401526040830152606082015260800190565b60405180910390a450505050565b5f6002821015611fa857505f6107c9565b5050613b8160f11b90356001600160601b0319161490565b5f5f60175f5f853c505f516001600160e81b0319811661ef0160f01b14612077575f836001600160a01b03163b1161202f5760405162461bcd60e51b815260206004820152601260248201527173656e64657220686173206e6f20636f646560701b6044820152606401610604565b60405162461bcd60e51b815260206004820152601860248201527f6e6f7420616e204549502d373730322064656c656761746500000000000000006044820152606401610604565b60481c6001600160a01b031692915050565b60605f6120996020850185613594565b905060208401355f8481036120c2576120bd6120b86040880188613904565b612602565b6120c4565b845b90505f6120d76120b86060890189613904565b9050608087013560a088013560c08901355f6120f96120b860e08d018d613904565b604080517f29a0bca4af4be3421398da00295e58e6d7de38cb492214754cb6a47507dd6f8e60208201526001600160a01b039a909a168a82015260608a019890985260808901969096525060a087019390935260c086019190915260e0850152610100840152610120808401919091528151808403909101815261014090920190529392505050565b80825d5050565b5f5f5f5a845190915061219c8682612614565b5f6121a660405190565b90506121b187610be9565b60208701526121bf81604052565b604082015161012083015161010084015160a08501516080860151606087015160c088015186171717171717896effffffffffffffffffffffffffffff8211156122535760408051631101335b60e11b815260048101929092526024820152601860448201527f41413934206761732076616c756573206f766572666c6f7700000000000000006064820152608401610604565b505f6122828560c081015160a08201516080830151606084015160408501516101009095015194010101010290565b60408a0181905290506122978b8b8b84612758565b97506122aa855f0151866020015161283f565b8b906123005760408051631101335b60e11b815260048101929092526024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152608401610604565b50825a8703111561235d578a604051631101335b60e11b8152600401610604918152604060208201819052601e908201527f41413236206f76657220766572696669636174696f6e4761734c696d69740000606082015260800190565b60e08501516060906001600160a01b0316156123835761237e8c8c8c61288b565b985090505b8060608b015260a08b01355a8803018a608001818152505050505050505050935093915050565b5f5f6123b58561298f565b91509150816001600160a01b0316836001600160a01b03161461241b5785604051631101335b60e11b81526004016106049181526040602082018190526014908201527320a0991a1039b4b3b730ba3ab9329032b93937b960611b606082015260800190565b80156124735785604051631101335b60e11b81526004016106049181526040602082018190526017908201527f414132322065787069726564206f72206e6f7420647565000000000000000000606082015260800190565b5f61247d8561298f565b925090506001600160a01b038116156124d95786604051631101335b60e11b81526004016106049181526040602082018190526014908201527320a0999a1039b4b3b730ba3ab9329032b93937b960611b606082015260800190565b811561253b5786604051631101335b60e11b81526004016106049181526040602082018190526021908201527f41413332207061796d61737465722065787069726564206f72206e6f742064756060820152606560f81b608082015260a00190565b50505050505050565b606060ff831461255e57612557836129df565b90506107c9565b81805461256a90613cf5565b80601f016020809104026020016040519081016040528092919081815260200182805461259690613cf5565b80156125e15780601f106125b8576101008083540402835291602001916125e1565b820191905f5260205f20905b8154815290600101906020018083116125c457829003601f168201915b505050505090506107c9565b5f8183106125fb5781610c2a565b5090919050565b5f604051828085833790209392505050565b6126216020830183613594565b6001600160a01b03168152602080830135908201526126436080830135612a1c565b6060830152604082015260a082013560c08083019190915261266790830135612a1c565b610100830152610120820152365f61268260e0850185613904565b909250905080156111fa5760348110156126de5760405162461bcd60e51b815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606401610604565b5f6126e98383612a3b565b60a0870152608086015290506001600160a01b0381166127445760405162461bcd60e51b815260206004820152601660248201527520a09c9c1034b73b30b634b2103830bcb6b0b9ba32b960511b6044820152606401610604565b6001600160a01b031660e084015250505050565b815180515f9190612776878661277160408a018a613904565b612aa2565b60e08201515f6001600160a01b0382166127b7576001600160a01b0383165f908152602081905260409020548681116127b1578087036127b3565b5f5b9150505b6127c389898984612e67565b94506001600160a01b038216612833576127dd8387612f89565b6128335788604051631101335b60e11b81526004016106049181526040602082018190526017908201527f41413231206469646e2774207061792070726566756e64000000000000000000606082015260800190565b50505050949350505050565b6001600160a01b0382165f90815260016020908152604080832084821c80855292528220805484916001600160401b03831691908561287d836137d9565b909155501495945050505050565b60605f5f5a845160e0810151604087015192935090916128ab8282612f89565b6129015788604051631101335b60e11b8152600401610604918152604060208201819052601e908201527f41413331207061796d6173746572206465706f73697420746f6f206c6f770000606082015260800190565b60808301516129118a8a8a612fc2565b9097509550805a860311156129825789604051631101335b60e11b81526004016106049181526040602082018190526027908201527f41413336206f766572207061796d6173746572566572696669636174696f6e47606082015266185cd31a5b5a5d60ca1b608082015260a00190565b5050505050935093915050565b5f5f825f036129a257505f928392509050565b5f6129ac846130cb565b9050806040015165ffffffffffff164211806129d45750806020015165ffffffffffff164211155b905194909350915050565b60605f6129eb8361313a565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f5f612a288360801c90565b6001600160801b03841691509150915091565b5f8080612a4b6014828688613b74565b612a5491613d2d565b60601c612a65602460148789613b74565b612a6e91613d6b565b60801c612a7f60346024888a613b74565b612a8891613d6b565b9194506001600160801b0316925060801c90509250925092565b80156111fa57825151612ab58383611f97565b15612b5b576014821115612b55578351604001516001600160a01b037f000000000000000000000000bbd9cebbb6565bf6f35c5ee8abaa6cebfd8a07ff169063c09ad0d99083612b08866014818a613b74565b6040518563ffffffff1660e01b8152600401612b2693929190613da1565b5f604051808303815f88803b158015612b3d575f5ffd5b5087f1158015612b4f573d5f5f3e3d5ffd5b50505050505b506111fa565b6001600160a01b0381163b15612bbd5784604051631101335b60e11b8152600401610604918152604060208201819052601f908201527f414131302073656e64657220616c726561647920636f6e737472756374656400606082015260800190565b6014821015612c185784604051631101335b60e11b81526004016106049181526040602082018190526017908201527f4141393920696e6974436f646520746f6f20736d616c6c000000000000000000606082015260800190565b5f7f000000000000000000000000bbd9cebbb6565bf6f35c5ee8abaa6cebfd8a07ff6001600160a01b031663570e1a36865f01516040015186866040518463ffffffff1660e01b8152600401612c6f929190613dce565b6020604051808303815f8887f1158015612c8b573d5f5f3e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190612cb09190613872565b90506001600160a01b038116612d125785604051631101335b60e11b8152600401610604918152604060208201819052601b908201527f4141313320696e6974436f6465206661696c6564206f72204f4f470000000000606082015260800190565b816001600160a01b0316816001600160a01b031614612d7c5785604051631101335b60e11b815260040161060491815260406020808301829052908201527f4141313420696e6974436f6465206d7573742072657475726e2073656e646572606082015260800190565b806001600160a01b03163b5f03612dde5785604051631101335b60e11b815260040161060491815260406020808301829052908201527f4141313520696e6974436f6465206d757374206372656174652073656e646572606082015260800190565b5f612dec6014828688613b74565b612df591613d2d565b60601c9050826001600160a01b031686602001517fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d83895f015160e00151604051612e569291906001600160a01b0392831681529116602082015260400190565b60405180910390a350505050505050565b8151604081015190515f91908280612e7e60405190565b90505f88886020015188604051602401612e9a93929190613de1565b60408051601f19818403018152919052602080820180516001600160e01b03166306608bdf60e21b178152825192935090915f9182888af192505f51955060203d14612ee4575f92505b612eed82604052565b505080612f7e57816001600160a01b03163b5f03612f575787604051631101335b60e11b81526004016106049181526040602082018190526019908201527f41413230206163636f756e74206e6f74206465706c6f79656400000000000000606082015260800190565b87612f63610800611556565b6040516365c8fd4d60e01b8152600401610604929190613e05565b505050949350505050565b6001600160a01b0382165f908152602081905260408120805483811015612fb4575f925050506107c9565b839003905550600192915050565b60605f5f612fcf60405190565b90505f8585602001518660400151604051602401612fef93929190613de1565b60408051601f198184030181529190526020810180516001600160e01b03166314add44b60e21b178152865160e08101516080909101518351939450909290915f9182918291829182918291829190828b8bf194503d9050805f8a3e6020890151995088519250606081039150604089019a508a519350841580613074575082604014155b8061308157508184601f01105b156130ad578d613092610800611556565b6040516365c8fd4d60e01b8152600401610604929190613e41565b601f8101601f19168901604052505050505050505050935093915050565b604080516060810182525f80825260208201819052918101919091528160a081901c65ffffffffffff81165f03613105575065ffffffffffff5b604080516060810182526001600160a01b03909316835260d09490941c602083015265ffffffffffff16928101929092525090565b5f60ff8216601f8111156107c957604051632cd44ac360e21b815260040160405180910390fd5b6040518060a001604052806131ca6040518061014001604052805f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81526020015f81525090565b81526020015f81526020015f81526020015f81526020015f81525090565b634e487b7160e01b5f52604160045260245ffd5b60405160a081016001600160401b038111828210171561321e5761321e6131e8565b60405290565b60405161014081016001600160401b038111828210171561321e5761321e6131e8565b5f82601f830112613256575f5ffd5b81356001600160401b0381111561326f5761326f6131e8565b604051601f8201601f19908116603f011681016001600160401b038111828210171561329d5761329d6131e8565b6040528181528382016020018510156132b4575f5ffd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b03811681146132e4575f5ffd5b50565b80356132f2816132d0565b919050565b5f5f83601f840112613307575f5ffd5b5081356001600160401b0381111561331d575f5ffd5b602083019150836020828501011115613334575f5ffd5b9250929050565b5f5f5f5f848603610200811215613350575f5ffd5b85356001600160401b03811115613365575f5ffd5b61337188828901613247565b955050601f19016101c0811215613386575f5ffd5b61338e6131fc565b61014082121561339c575f5ffd5b6133a4613224565b91506133b2602088016132e7565b82526040878101356020840152606080890135918401919091526080808901359184019190915260a0808901359184019190915260c0808901359184019190915260e08801359083015261340961010088016132e7565b60e08301526101208781013561010084015261014088013590830152908152610160860135602082015261018086013560408201526101a086013560608201526101c0860135608082015292506101e08501356001600160401b0381111561346f575f5ffd5b61347b878288016132f7565b95989497509550505050565b5f60208284031215613497575f5ffd5b81356001600160e01b031981168114610c2a575f5ffd5b5f602082840312156134be575f5ffd5b813563ffffffff81168114610c2a575f5ffd5b80356001600160c01b03811681146132f2575f5ffd5b5f602082840312156134f7575f5ffd5b610c2a826134d1565b5f5f60408385031215613511575f5ffd5b823561351c816132d0565b915061352a602084016134d1565b90509250929050565b5f5f60408385031215613544575f5ffd5b823561354f816132d0565b946020939093013593505050565b5f6020828403121561356d575f5ffd5b81356001600160401b03811115613582575f5ffd5b82016101208185031215610c2a575f5ffd5b5f602082840312156135a4575f5ffd5b8135610c2a816132d0565b5f5f83601f8401126135bf575f5ffd5b5081356001600160401b038111156135d5575f5ffd5b6020830191508360208260051b8501011115613334575f5ffd5b5f5f5f60408486031215613601575f5ffd5b83356001600160401b03811115613616575f5ffd5b613622868287016135af565b9094509250506020840135613636816132d0565b809150509250925092565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f61368d60e0830189613641565b828103604084015261369f8189613641565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b818110156136f45783518352602093840193909201916001016136d6565b50909b9a5050505050505050505050565b5f5f5f60408486031215613717575f5ffd5b8335613722816132d0565b925060208401356001600160401b0381111561373c575f5ffd5b613748868287016132f7565b9497909650939450505050565b5f60208284031215613765575f5ffd5b81356001600160401b0381111561377a575f5ffd5b611ea584828501613247565b634e487b7160e01b5f52601260045260245ffd5b828152604060208201525f611ea56040830184613641565b634e487b7160e01b5f52601160045260245ffd5b808201808211156107c9576107c96137b2565b5f600182016137ea576137ea6137b2565b5060010190565b818103818111156107c9576107c96137b2565b634e487b7160e01b5f52603260045260245ffd5b5f823561011e1983360301811261382d575f5ffd5b9190910192915050565b818382375f9101908152919050565b8215158152604060208201525f611ea56040830184613641565b602081525f610c2a6020830184613641565b5f60208284031215613882575f5ffd5b8151610c2a816132d0565b65ffffffffffff81811683821601908111156107c9576107c96137b2565b5f8235605e1983360301811261382d575f5ffd5b5f5f8335601e198436030181126138d4575f5ffd5b8301803591506001600160401b038211156138ed575f5ffd5b6020019150600581901b3603821315613334575f5ffd5b5f5f8335601e19843603018112613919575f5ffd5b8301803591506001600160401b03821115613932575f5ffd5b602001915036819003821315613334575f5ffd5b5f5f8335601e1984360301811261395b575f5ffd5b83016020810192503590506001600160401b03811115613979575f5ffd5b803603821315613334575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6139c9826139bc836132e7565b6001600160a01b03169052565b602081810135908301525f6139e16040830183613946565b61012060408601526139f861012086018284613987565b915050613a086060840184613946565b8583036060870152613a1b838284613987565b6080868101359088015260a0808701359088015260c080870135908801529250613a4b91505060e0840184613946565b85830360e0870152613a5e838284613987565b92505050613a70610100840184613946565b858303610100870152613a84838284613987565b9695505050505050565b604080825281018490525f6060600586901b83018101908301878361011e1936839003015b89821015613af757868503605f190184528235818112613ad1575f5ffd5b613add868d83016139af565b955050602083019250602084019350600182019150613ab3565b505050508281036020840152613b0e818587613987565b979650505050505050565b634e487b7160e01b5f52602160045260245ffd5b5f60038610613b4a57634e487b7160e01b5f52602160045260245ffd5b85825260806020830152613b616080830186613641565b6040830194909452506060015292915050565b5f5f85851115613b82575f5ffd5b83861115613b8e575f5ffd5b5050820193919092039150565b6001600160601b03198460601b168152818360148301375f910160140190815292915050565b604081525f613bd360408301856139af565b90508260208301529392505050565b805180516001600160a01b031683526020810151602084015260408101516040840152606081015160608401526080810151608084015260a081015160a084015260c081015160c084015260e0810151613c4760e08501826001600160a01b03169052565b5061010081810151908401526101209081015190830152602081015161014083015260408101516101608301526060810151610180830152608001516101a090910152565b61020081525f613ca0610200830186613641565b613cad6020840186613be2565b8281036101e0840152613a848185613641565b61020081525f613cd561020083018688613987565b613ce26020840186613be2565b8281036101e0840152613b0e8185613641565b600181811c90821680613d0957607f821691505b602082108103613d2757634e487b7160e01b5f52602260045260245ffd5b50919050565b80356001600160601b03198116906014841015613d64576001600160601b03196001600160601b03198560140360031b1b82161691505b5092915050565b80356001600160801b03198116906010841015613d64576001600160801b031960109490940360031b84901b1690921692915050565b6001600160a01b03841681526040602082018190525f90613dc59083018486613987565b95945050505050565b602081525f611ea5602083018486613987565b606081525f613df360608301866139af565b60208301949094525060400152919050565b82815260606020820152600d60608201526c10504c8cc81c995d995c9d1959609a1b608082015260a060408201525f611ea560a0830184613641565b82815260606020820152600d60608201526c10504cccc81c995d995c9d1959609a1b608082015260a060408201525f611ea560a083018461364156fea2646970667358221220740811fa439297b941d35bd6f03090191190666139feccfe49c6930a75cfe6ec64736f6c634300081e0033
logo
GateScan is the official explorer and analytics platform for Gate Chain and Gate Layer.