Sepolia Testnet

Contract

0xd3082872F8B06073A021b4602e022d5A070d7cfC

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
53394662024-02-22 7:26:48291 days ago1708586808  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Kernel

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 17 : Kernel.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Importing external libraries and contracts
import {EIP712} from "solady/utils/EIP712.sol";
import {ECDSA} from "solady/utils/ECDSA.sol";
import {IEntryPoint} from "I4337/interfaces/IEntryPoint.sol";
import {UserOperation} from "I4337/interfaces/UserOperation.sol";
import {Compatibility} from "./abstract/Compatibility.sol";
import {KernelStorage} from "./abstract/KernelStorage.sol";
import {_intersectValidationData} from "./utils/KernelHelper.sol";
import {IKernelValidator} from "./interfaces/IKernelValidator.sol";

import {
    KERNEL_NAME,
    KERNEL_VERSION,
    VALIDATOR_APPROVED_STRUCT_HASH,
    KERNEL_STORAGE_SLOT_1,
    SIG_VALIDATION_FAILED
} from "./common/Constants.sol";
import {Operation} from "./common/Enums.sol";
import {WalletKernelStorage, Call, ExecutionDetail} from "./common/Structs.sol";
import {ValidationData, ValidAfter, ValidUntil, parseValidationData, packValidationData} from "./common/Types.sol";

/// @title Kernel
/// @author taek<[email protected]>
/// @notice wallet kernel for extensible wallet functionality
contract Kernel is EIP712, Compatibility, KernelStorage {
    /// @dev Selector of the `DisabledMode()` error, to be used in assembly, 'bytes4(keccak256(bytes("DisabledMode()")))', same as DisabledMode.selector()
    uint256 private constant _DISABLED_MODE_SELECTOR = 0xfc2f51c5;
    bytes32 internal constant EIP712_DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    /// @dev Current kernel name and version
    string public constant name = KERNEL_NAME;
    string public constant version = KERNEL_VERSION;

    /// @dev Sets up the EIP712 and KernelStorage with the provided entry point
    constructor(IEntryPoint _entryPoint) KernelStorage(_entryPoint) {}

    /// @notice Accepts incoming Ether transactions and calls from the EntryPoint contract
    /// @dev This function will delegate any call to the appropriate executor based on the function signature.
    fallback() external payable {
        bytes4 sig = msg.sig;
        address executor = getKernelStorage().execution[sig].executor;
        if (msg.sender != address(entryPoint) && !_checkCaller()) {
            revert NotAuthorizedCaller();
        }
        assembly {
            calldatacopy(0, 0, calldatasize())
            let result := delegatecall(gas(), executor, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            switch result
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }

    /// @notice Executes a function call to an external contract
    /// @param to The address of the target contract
    /// @param value The amount of Ether to send
    /// @param data The call data to be sent
    /// @dev operation is deprecated param, use executeBatch for batched transaction
    function execute(address to, uint256 value, bytes memory data, Operation _operation) external payable {
        if (msg.sender != address(entryPoint) && msg.sender != address(this) && !_checkCaller()) {
            revert NotAuthorizedCaller();
        }
        if (_operation != Operation.Call) {
            revert DeprecatedOperation();
        }
        assembly {
            let success := call(gas(), to, value, add(data, 0x20), mload(data), 0, 0)
            returndatacopy(0, 0, returndatasize())
            switch success
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }

    /// @notice Executes a function call to an external contract with delegatecall
    /// @param to The address of the target contract
    /// @param data The call data to be sent
    function executeDelegateCall(address to, bytes memory data) external payable {
        if (msg.sender != address(entryPoint) && msg.sender != address(this) && !_checkCaller()) {
            revert NotAuthorizedCaller();
        }
        assembly {
            let success := delegatecall(gas(), to, add(data, 0x20), mload(data), 0, 0)
            returndatacopy(0, 0, returndatasize())
            switch success
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }

    /// @notice Executes a function call to an external contract batched
    /// @param calls The calls to be executed, in order
    /// @dev operation deprecated param, use executeBatch for batched transaction
    function executeBatch(Call[] memory calls) external payable {
        if (msg.sender != address(entryPoint) && !_checkCaller()) {
            revert NotAuthorizedCaller();
        }
        uint256 len = calls.length;
        for (uint256 i = 0; i < len;) {
            Call memory call = calls[i];
            address to = call.to;
            uint256 value = call.value;
            bytes memory data = call.data;
            assembly {
                let success := call(gas(), to, value, add(data, 0x20), mload(data), 0, 0)
                switch success
                case 0 {
                    returndatacopy(0, 0, returndatasize())
                    revert(0, returndatasize())
                }
                default { i := add(i, 1) }
            }
        }
    }

    /// @notice Validates a user operation based on its mode
    /// @dev This function will validate user operation and be called by EntryPoint
    /// @param _userOp The user operation to be validated
    /// @param userOpHash The hash of the user operation
    /// @param missingAccountFunds The funds needed to be reimbursed
    /// @return validationData The data used for validation
    function validateUserOp(UserOperation calldata _userOp, bytes32 userOpHash, uint256 missingAccountFunds)
        external
        payable
        virtual
        returns (ValidationData validationData)
    {
        if (msg.sender != address(entryPoint)) {
            revert NotEntryPoint();
        }
        bytes calldata userOpSignature;
        uint256 userOpEndOffset;
        assembly {
            // Store the userOpSignature offset
            userOpEndOffset := add(calldataload(0x04), 0x24)
            // Extract the user op signature from the calldata (but keep it in the calldata, just extract offset & length)
            userOpSignature.offset := add(calldataload(add(userOpEndOffset, 0x120)), userOpEndOffset)
            userOpSignature.length := calldataload(sub(userOpSignature.offset, 0x20))
        }
        // mode based signature
        bytes4 mode = bytes4(userOpSignature[0:4]); // mode == 00..00 use validators
        // mode == 0x00000000 use sudo validator
        if (mode == 0x00000000) {
            assembly {
                if missingAccountFunds {
                    pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue()))
                    //ignore failure (its EntryPoint's job to verify, not account.)
                }
            }
            // short circuit here for default validator
            return _validateUserOp(_userOp, userOpHash, missingAccountFunds);
        }

        // Check if the kernel is disabled, if that's the case, it's only accepting userOperation with sudo mode
        assembly ("memory-safe") {
            // Extract the disabled mode from the storage slot
            let isKernelDisabled := shl(224, sload(KERNEL_STORAGE_SLOT_1))
            // If we got a non-zero disabled mode, and non zero mode, then revert
            if and(isKernelDisabled, mode) {
                mstore(0x00, _DISABLED_MODE_SELECTOR)
                revert(0x1c, 0x04)
            }
        }

        // The validator that will be used
        IKernelValidator validator;

        // mode == 0x00000001 use given validator
        // mode == 0x00000002 enable validator
        if (mode == 0x00000001) {
            bytes calldata userOpCallData;
            assembly {
                userOpCallData.offset := add(calldataload(add(userOpEndOffset, 0x40)), userOpEndOffset)
                userOpCallData.length := calldataload(sub(userOpCallData.offset, 0x20))
            }
            ExecutionDetail storage detail = getKernelStorage().execution[bytes4(userOpCallData[0:4])];
            validator = detail.validator;
            userOpSignature = userOpSignature[4:];
            validationData = packValidationData(detail.validAfter, detail.validUntil);
        } else if (mode == 0x00000002) {
            bytes calldata userOpCallData;
            assembly {
                userOpCallData.offset := add(calldataload(add(userOpEndOffset, 0x40)), userOpEndOffset)
                userOpCallData.length := calldataload(sub(userOpCallData.offset, 0x20))
            }
            // use given validator
            // userOpSignature[4:10] = validAfter,
            // userOpSignature[10:16] = validUntil,
            // userOpSignature[16:36] = validator address,
            (validator, validationData, userOpSignature) =
                _approveValidator(bytes4(userOpCallData[0:4]), userOpSignature);
        } else {
            return SIG_VALIDATION_FAILED;
        }

        assembly {
            if missingAccountFunds {
                pop(call(gas(), caller(), missingAccountFunds, callvalue(), callvalue(), callvalue(), callvalue()))
                //ignore failure (its EntryPoint's job to verify, not account.)
            }
        }

        // Replicate the userOp from memory to calldata, to update it's signature (since with mode 1 & 2 the signatre can be updated)
        UserOperation memory userOp = _userOp;
        userOp.signature = userOpSignature;

        // Get the validator data from the designated signer
        validationData =
            _intersectValidationData(validationData, validator.validateUserOp(userOp, userOpHash, missingAccountFunds));
        return validationData;
    }

    /// @dev This function will approve a new validator for the current kernel
    /// @param sig The signature of the userOp asking for a validator approval
    /// @param signature The signature of the userOp asking for a validator approval
    function _approveValidator(bytes4 sig, bytes calldata signature)
        internal
        returns (IKernelValidator validator, ValidationData validationData, bytes calldata validationSig)
    {
        unchecked {
            validator = IKernelValidator(address(bytes20(signature[16:36])));
            uint256 cursor = 88;
            uint256 length = uint256(bytes32(signature[56:88])); // this is enableDataLength
            bytes calldata enableData;
            assembly {
                enableData.offset := add(signature.offset, cursor)
                enableData.length := length
                cursor := add(cursor, length) // 88 + enableDataLength
            }
            length = uint256(bytes32(signature[cursor:cursor + 32])); // this is enableSigLength
            assembly {
                cursor := add(cursor, 32)
            }
            bytes32 enableDigest = _hashTypedData(
                keccak256(
                    abi.encode(
                        VALIDATOR_APPROVED_STRUCT_HASH,
                        bytes4(sig),
                        uint256(bytes32(signature[4:36])),
                        address(bytes20(signature[36:56])),
                        keccak256(enableData)
                    )
                )
            );
            validationData = _intersectValidationData(
                _validateSignature(address(this), enableDigest, enableDigest, signature[cursor:cursor + length]),
                ValidationData.wrap(
                    uint256(bytes32(signature[4:36]))
                        & 0xffffffffffffffffffffffff0000000000000000000000000000000000000000
                )
            );
            assembly {
                cursor := add(cursor, length)
                validationSig.offset := add(signature.offset, cursor)
                validationSig.length := sub(signature.length, cursor)
            }
            getKernelStorage().execution[sig] = ExecutionDetail({
                validAfter: ValidAfter.wrap(uint48(bytes6(signature[4:10]))),
                validUntil: ValidUntil.wrap(uint48(bytes6(signature[10:16]))),
                executor: address(bytes20(signature[36:56])),
                validator: IKernelValidator(address(bytes20(signature[16:36])))
            });
            validator.enable(enableData);
        }
    }

    /// @dev Validates a signature for the given kernel
    /// @param hash The hash of the data that was signed
    /// @param signature The signature to be validated
    function validateSignature(bytes32 hash, bytes calldata signature) public view returns (ValidationData) {
        return _validateSignature(msg.sender, hash, hash, signature);
    }

    /// @dev Get the current name & version of the kernel, used for the EIP-712 domain separator
    function _domainNameAndVersion() internal pure override returns (string memory, string memory) {
        return (name, version);
    }

    /// @dev Get an EIP-712 compliant domain separator
    function _domainSeparator() internal view override returns (bytes32) {
        // Obtain the name and version from the _domainNameAndVersion function.
        (string memory _name, string memory _version) = _domainNameAndVersion();
        bytes32 nameHash = keccak256(bytes(_name));
        bytes32 versionHash = keccak256(bytes(_version));

        // Use the proxy address for the EIP-712 domain separator.
        address proxyAddress = address(this);

        // Construct the domain separator with name, version, chainId, and proxy address.
        bytes32 typeHash = EIP712_DOMAIN_TYPEHASH;
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, proxyAddress));
    }

    /// @notice Checks if a signature is valid
    /// @dev This function checks if a signature is valid based on the hash of the data signed.
    /// @param hash The hash of the data that was signed
    /// @param signature The signature to be validated
    /// @return The magic value 0x1626ba7e if the signature is valid, otherwise returns 0xffffffff.
    function isValidSignature(bytes32 hash, bytes calldata signature) public view returns (bytes4) {
        // Include the proxy address in the domain separator
        bytes32 domainSeparator = _domainSeparator();

        // Recreate the signed message hash with the correct domain separator
        bytes32 signedMessageHash = keccak256(abi.encodePacked("\x19\x01", domainSeparator, hash));

        ValidationData validationData = _validateSignature(msg.sender, signedMessageHash, hash, signature);
        (ValidAfter validAfter, ValidUntil validUntil, address result) = parseValidationData(validationData);

        // Check if the signature is valid within the specified time frame and the result is successful
        if (
            ValidAfter.unwrap(validAfter) <= block.timestamp && ValidUntil.unwrap(validUntil) >= block.timestamp
                && result == address(0)
        ) {
            // If all checks pass, return the ERC1271 magic value for a valid signature
            return 0x1626ba7e;
        } else {
            // If any check fails, return the failure magic value
            return 0xffffffff;
        }
    }

    /// @dev Check if the current caller is authorized or no to perform the call
    /// @return True if the caller is authorized, otherwise false
    function _checkCaller() internal returns (bool) {
        if (_validCaller(msg.sender, msg.data)) {
            return true;
        }
        bytes4 sig = msg.sig;
        ExecutionDetail storage detail = getKernelStorage().execution[sig];
        if (
            address(detail.validator) == address(0)
                || (ValidUntil.unwrap(detail.validUntil) != 0 && ValidUntil.unwrap(detail.validUntil) < block.timestamp)
                || ValidAfter.unwrap(detail.validAfter) > block.timestamp
        ) {
            return false;
        } else {
            return detail.validator.validCaller(msg.sender, msg.data);
        }
    }

    /// @dev This function will validate user operation and be called by EntryPoint
    /// @param _op The user operation to be validated
    /// @param _opHash The hash of the user operation
    /// @param _missingFunds The funds needed to be reimbursed
    function _validateUserOp(UserOperation calldata _op, bytes32 _opHash, uint256 _missingFunds)
        internal
        virtual
        returns (ValidationData)
    {
        // Replace the user op in memory to update the signature
        UserOperation memory op = _op;
        // Remove the validation mode flag from the signature
        op.signature = _op.signature[4:];

        IKernelValidator validator;
        assembly {
            validator := shr(80, sload(KERNEL_STORAGE_SLOT_1))
        }
        return IKernelValidator(validator).validateUserOp(op, _opHash, _missingFunds);
    }

    /// @dev This function will validate a signature for the given kernel
    /// @param _hash The hash of the data that was signed
    /// @param _signature The signature to be validated
    /// @return The magic value 0x1626ba7e if the signature is valid, otherwise returns 0xffffffff.
    function _validateSignature(address _requestor, bytes32 _hash, bytes32 _rawHash, bytes calldata _signature)
        internal
        view
        virtual
        returns (ValidationData)
    {
        address validator;
        assembly {
            validator := shr(80, sload(KERNEL_STORAGE_SLOT_1))
        }
        // 20 bytes added at the end of the signature to store the address of the caller
        (bool success, bytes memory res) = validator.staticcall(
            abi.encodePacked(
                abi.encodeWithSelector(IKernelValidator.validateSignature.selector, _hash, _signature),
                _rawHash,
                _requestor
            )
        );
        require(success, "Kernel::_validateSignature: failed to validate signature");
        return abi.decode(res, (ValidationData));
    }

    /// @dev Check if the given caller is valid for the given data
    /// @param _caller The caller to be checked
    /// @param _data The data to be checked
    /// @return True if the caller is valid, otherwise false
    function _validCaller(address _caller, bytes calldata _data) internal virtual returns (bool) {
        address validator;
        assembly {
            // Load the validator from the storage slot
            validator := shr(80, sload(KERNEL_STORAGE_SLOT_1))
        }
        return IKernelValidator(validator).validCaller(_caller, _data);
    }
}

File 2 of 17 : EIP712.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Contract for EIP-712 typed structured data hashing and signing.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)
/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)
///
/// @dev Note, this implementation:
/// - Uses `address(this)` for the `verifyingContract` field.
/// - Does NOT use the optional EIP-712 salt.
/// - Does NOT use any EIP-712 extensions.
/// This is for simplicity and to save gas.
/// If you need to customize, please fork / modify accordingly.
abstract contract EIP712 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  CONSTANTS AND IMMUTABLES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`.
    bytes32 internal constant _DOMAIN_TYPEHASH =
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    uint256 private immutable _cachedThis;
    uint256 private immutable _cachedChainId;
    bytes32 private immutable _cachedNameHash;
    bytes32 private immutable _cachedVersionHash;
    bytes32 private immutable _cachedDomainSeparator;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CONSTRUCTOR                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Cache the hashes for cheaper runtime gas costs.
    /// In the case of upgradeable contracts (i.e. proxies),
    /// or if the chain id changes due to a hard fork,
    /// the domain separator will be seamlessly calculated on-the-fly.
    constructor() {
        _cachedThis = uint256(uint160(address(this)));
        _cachedChainId = block.chainid;

        string memory name;
        string memory version;
        if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion();
        bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name));
        bytes32 versionHash =
            _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version));
        _cachedNameHash = nameHash;
        _cachedVersionHash = versionHash;

        bytes32 separator;
        if (!_domainNameAndVersionMayChange()) {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Load the free memory pointer.
                mstore(m, _DOMAIN_TYPEHASH)
                mstore(add(m, 0x20), nameHash)
                mstore(add(m, 0x40), versionHash)
                mstore(add(m, 0x60), chainid())
                mstore(add(m, 0x80), address())
                separator := keccak256(m, 0xa0)
            }
        }
        _cachedDomainSeparator = separator;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   FUNCTIONS TO OVERRIDE                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Please override this function to return the domain name and version.
    /// ```
    ///     function _domainNameAndVersion()
    ///         internal
    ///         pure
    ///         virtual
    ///         returns (string memory name, string memory version)
    ///     {
    ///         name = "Solady";
    ///         version = "1";
    ///     }
    /// ```
    ///
    /// Note: If the returned result may change after the contract has been deployed,
    /// you must override `_domainNameAndVersionMayChange()` to return true.
    function _domainNameAndVersion()
        internal
        view
        virtual
        returns (string memory name, string memory version);

    /// @dev Returns if `_domainNameAndVersion()` may change
    /// after the contract has been deployed (i.e. after the constructor).
    /// Default: false.
    function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {}

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _domainSeparator() internal view virtual returns (bytes32 separator) {
        if (_domainNameAndVersionMayChange()) {
            separator = _buildDomainSeparator();
        } else {
            separator = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator();
        }
    }

    /// @dev Returns the hash of the fully encoded EIP-712 message for this domain,
    /// given `structHash`, as defined in
    /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.
    ///
    /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:
    /// ```
    ///     bytes32 digest = _hashTypedData(keccak256(abi.encode(
    ///         keccak256("Mail(address to,string contents)"),
    ///         mailTo,
    ///         keccak256(bytes(mailContents))
    ///     )));
    ///     address signer = ECDSA.recover(digest, signature);
    /// ```
    function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) {
        // We will use `digest` to store the domain separator to save a bit of gas.
        if (_domainNameAndVersionMayChange()) {
            digest = _buildDomainSeparator();
        } else {
            digest = _cachedDomainSeparator;
            if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator();
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the digest.
            mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
            mstore(0x1a, digest) // Store the domain separator.
            mstore(0x3a, structHash) // Store the struct hash.
            digest := keccak256(0x18, 0x42)
            // Restore the part of the free memory slot that was overwritten.
            mstore(0x3a, 0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    EIP-5267 OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev See: https://eips.ethereum.org/EIPS/eip-5267
    function eip712Domain()
        public
        view
        virtual
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        )
    {
        fields = hex"0f"; // `0b01111`.
        (name, version) = _domainNameAndVersion();
        chainId = block.chainid;
        verifyingContract = address(this);
        salt = salt; // `bytes32(0)`.
        extensions = extensions; // `new uint256[](0)`.
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the EIP-712 domain separator.
    function _buildDomainSeparator() private view returns (bytes32 separator) {
        // We will use `separator` to store the name hash to save a bit of gas.
        bytes32 versionHash;
        if (_domainNameAndVersionMayChange()) {
            (string memory name, string memory version) = _domainNameAndVersion();
            separator = keccak256(bytes(name));
            versionHash = keccak256(bytes(version));
        } else {
            separator = _cachedNameHash;
            versionHash = _cachedVersionHash;
        }
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Load the free memory pointer.
            mstore(m, _DOMAIN_TYPEHASH)
            mstore(add(m, 0x20), separator) // Name hash.
            mstore(add(m, 0x40), versionHash)
            mstore(add(m, 0x60), chainid())
            mstore(add(m, 0x80), address())
            separator := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns if the cached domain separator has been invalidated.
    function _cachedDomainSeparatorInvalidated() private view returns (bool result) {
        uint256 cachedChainId = _cachedChainId;
        uint256 cachedThis = _cachedThis;
        /// @solidity memory-safe-assembly
        assembly {
            result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))
        }
    }
}

File 3 of 17 : ECDSA.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
///
/// @dev Note:
/// - The recovery functions use the ecrecover precompile (0x1).
/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.
///   This is for more safety by default.
///   Use the `tryRecover` variants if you need to get the zero address back
///   upon recovery failure instead.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
///   See: https://eips.ethereum.org/EIPS/eip-2098
///   This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT use signatures as unique identifiers:
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
///   EIP-712 also enables readable signing of typed data for better user safety.
/// This implementation does NOT check if a signature is non-malleable.
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The signature is invalid.
    error InvalidSignature();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    RECOVERY OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            for {} 1 {} {
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                if eq(mload(signature), 64) {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(mload(signature), 65) {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    break
                }
                result := 0
                break
            }
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        result, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function recoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            for {} 1 {} {
                if eq(signature.length, 64) {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(signature.length, 65) {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                    break
                }
                result := 0
                break
            }
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        result, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, add(shr(255, vs), 27)) // `v`.
            mstore(0x40, r)
            mstore(0x60, shr(1, shl(1, vs))) // `s`.
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            result :=
                mload(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x01, // Start of output.
                        0x20 // Size of output.
                    )
                )
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                revert(0x1c, 0x04)
            }
            mstore(0x60, 0) // Restore the zero slot.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   TRY-RECOVER OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // WARNING!
    // These functions will NOT revert upon recovery failure.
    // Instead, they will return the zero address upon recovery failure.
    // It is critical that the returned address is NEVER compared against
    // a zero address (e.g. an uninitialized address variable).

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function tryRecover(bytes32 hash, bytes memory signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            for {} 1 {} {
                mstore(0x00, hash)
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                if eq(mload(signature), 64) {
                    let vs := mload(add(signature, 0x40))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(mload(signature), 65) {
                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                    mstore(0x60, mload(add(signature, 0x40))) // `s`.
                    break
                }
                result := 0
                break
            }
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    result, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
    function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := 1
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            for {} 1 {} {
                if eq(signature.length, 64) {
                    let vs := calldataload(add(signature.offset, 0x20))
                    mstore(0x20, add(shr(255, vs), 27)) // `v`.
                    mstore(0x40, calldataload(signature.offset)) // `r`.
                    mstore(0x60, shr(1, shl(1, vs))) // `s`.
                    break
                }
                if eq(signature.length, 65) {
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                    break
                }
                result := 0
                break
            }
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    result, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, add(shr(255, vs), 27)) // `v`.
            mstore(0x40, r)
            mstore(0x60, shr(1, shl(1, vs))) // `s`.
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    1, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the signature defined by `v`, `r`, `s`.
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    1, // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x40, // Start of output.
                    0x20 // Size of output.
                )
            )
            mstore(0x60, 0) // Restore the zero slot.
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            result := mload(xor(0x60, returndatasize()))
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     HASHING OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an Ethereum Signed Message, created from a `hash`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, hash) // Store into scratch space for keccak256.
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
        }
    }

    /// @dev Returns an Ethereum Signed Message, created from `s`.
    /// This produces a hash corresponding to the one signed with the
    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
    /// JSON-RPC method as part of EIP-191.
    /// Note: Supports lengths of `s` up to 999999 bytes.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let sLength := mload(s)
            let o := 0x20
            mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
            mstore(0x00, 0x00)
            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
            for { let temp := sLength } 1 {} {
                o := sub(o, 1)
                mstore8(o, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
            mstore(s, sLength) // Restore the length.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   EMPTY CALLDATA HELPERS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns an empty calldata bytes.
    function emptySignature() internal pure returns (bytes calldata signature) {
        /// @solidity memory-safe-assembly
        assembly {
            signature.length := 0
        }
    }
}

File 4 of 17 : IEntryPoint.sol
/**
 ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
 ** Only one instance required on each chain.
 **/
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;

/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-inline-assembly */
/* solhint-disable reason-string */

import "./UserOperation.sol";
import "./IStakeManager.sol";
import "./IAggregator.sol";
import "./INonceManager.sol";

interface IEntryPoint is IStakeManager, INonceManager {
    /***
     * An event emitted after each successful request.
     * @param userOpHash    - Unique identifier for the request (hash its entire content, except signature).
     * @param sender        - The account that generates this request.
     * @param paymaster     - If non-null, the paymaster that pays for this request.
     * @param nonce         - The nonce value from the request.
     * @param success       - True if the sender transaction succeeded, false if reverted.
     * @param actualGasCost - Actual amount paid (by account or paymaster) for this UserOperation.
     * @param actualGasUsed - Total gas used by this UserOperation (including preVerification, creation,
     *                        validation and execution).
     */
    event UserOperationEvent(
        bytes32 indexed userOpHash,
        address indexed sender,
        address indexed paymaster,
        uint256 nonce,
        bool success,
        uint256 actualGasCost,
        uint256 actualGasUsed
    );

    /**
     * Account "sender" was deployed.
     * @param userOpHash - The userOp that deployed this account. UserOperationEvent will follow.
     * @param sender     - The account that is deployed
     * @param factory    - The factory used to deploy this account (in the initCode)
     * @param paymaster  - The paymaster used by this UserOp
     */
    event AccountDeployed(
        bytes32 indexed userOpHash,
        address indexed sender,
        address factory,
        address paymaster
    );

    /**
     * An event emitted if the UserOperation "callData" reverted with non-zero length.
     * @param userOpHash   - The request unique identifier.
     * @param sender       - The sender of this request.
     * @param nonce        - The nonce used in the request.
     * @param revertReason - The return bytes from the (reverted) call to "callData".
     */
    event UserOperationRevertReason(
        bytes32 indexed userOpHash,
        address indexed sender,
        uint256 nonce,
        bytes revertReason
    );

    /**
     * An event emitted by handleOps(), before starting the execution loop.
     * Any event emitted before this event, is part of the validation.
     */
    event BeforeExecution();

    /**
     * Signature aggregator used by the following UserOperationEvents within this bundle.
     * @param aggregator - The aggregator used for the following UserOperationEvents.
     */
    event SignatureAggregatorChanged(address indexed aggregator);

    /**
     * A custom revert error of handleOps, to identify the offending op.
     * Should be caught in off-chain handleOps simulation and not happen on-chain.
     * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.
     * NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it.
     * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
     * @param reason  - Revert reason. The string starts with a unique code "AAmn",
     *                  where "m" is "1" for factory, "2" for account and "3" for paymaster issues,
     *                  so a failure can be attributed to the correct entity.
     */
    error FailedOp(uint256 opIndex, string reason);

    /**
     * Error case when a signature aggregator fails to verify the aggregated signature it had created.
     * @param aggregator The aggregator that failed to verify the signature
     */
    error SignatureValidationFailed(address aggregator);

    // Return value of getSenderAddress.
    error SenderAddressResult(address sender);

    // UserOps handled, per aggregator.
    struct UserOpsPerAggregator {
        UserOperation[] userOps;
        // Aggregator address
        IAggregator aggregator;
        // Aggregated signature
        bytes signature;
    }

    /**
     * Execute a batch of UserOperations.
     * No signature aggregator is used.
     * If any account requires an aggregator (that is, it returned an aggregator when
     * performing simulateValidation), then handleAggregatedOps() must be used instead.
     * @param ops         - The operations to execute.
     * @param beneficiary - The address to receive the fees.
     */
    function handleOps(
        UserOperation[] calldata ops,
        address payable beneficiary
    ) external;

    /**
     * Execute a batch of UserOperation with Aggregators
     * @param opsPerAggregator - The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts).
     * @param beneficiary      - The address to receive the fees.
     */
    function handleAggregatedOps(
        UserOpsPerAggregator[] calldata opsPerAggregator,
        address payable beneficiary
    ) external;

    /**
     * Generate a request Id - unique identifier for this request.
     * The request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.
     * @param userOp - The user operation to generate the request ID for.
     */
    function getUserOpHash(
        UserOperation calldata userOp
    ) external view returns (bytes32);

    /**
     * Gas and return values during simulation.
     * @param preOpGas         - The gas used for validation (including preValidationGas)
     * @param prefund          - The required prefund for this operation
     * @param sigFailed        - ValidateUserOp's (or paymaster's) signature check failed
     * @param validAfter       - First timestamp this UserOp is valid (merging account and paymaster time-range)
     * @param validUntil       - Last timestamp this UserOp is valid (merging account and paymaster time-range)
     * @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp)
     */
    struct ReturnInfo {
        uint256 preOpGas;
        uint256 prefund;
        bool sigFailed;
        uint48 validAfter;
        uint48 validUntil;
        bytes paymasterContext;
    }

    /**
     * Returned aggregated signature info:
     * The aggregator returned by the account, and its current stake.
     */
    struct AggregatorStakeInfo {
        address aggregator;
        StakeInfo stakeInfo;
    }

    /**
     * Get counterfactual sender address.
     * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.
     * This method always revert, and returns the address in SenderAddressResult error
     * @param initCode - The constructor code to be passed into the UserOperation.
     */
    function getSenderAddress(bytes memory initCode) external;

}

File 5 of 17 : UserOperation.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;

/* solhint-disable no-inline-assembly */

/**
 * User Operation struct
 * @param sender                - The sender account of this request.
 * @param nonce                 - Unique value the sender uses to verify it is not a replay.
 * @param initCode              - If set, the account contract will be created by this constructor/
 * @param callData              - The method call to execute on this account.
 * @param callGasLimit          - The gas limit passed to the callData method call.
 * @param verificationGasLimit  - Gas used for validateUserOp and validatePaymasterUserOp.
 * @param preVerificationGas    - Gas not calculated by the handleOps method, but added to the gas paid.
 *                                Covers batch overhead.
 * @param maxFeePerGas          - Same as EIP-1559 gas parameter.
 * @param maxPriorityFeePerGas  - Same as EIP-1559 gas parameter.
 * @param paymasterAndData      - If set, this field holds the paymaster address and paymaster-specific data.
 *                                The paymaster will pay for the transaction instead of the sender.
 * @param signature             - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.
 */
struct UserOperation {
    address sender;
    uint256 nonce;
    bytes initCode;
    bytes callData;
    uint256 callGasLimit;
    uint256 verificationGasLimit;
    uint256 preVerificationGas;
    uint256 maxFeePerGas;
    uint256 maxPriorityFeePerGas;
    bytes paymasterAndData;
    bytes signature;
}

File 6 of 17 : Compatibility.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

abstract contract Compatibility {
    event Received(address sender, uint256 amount);

    receive() external payable {
        emit Received(msg.sender, msg.value);
    }

    function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
        return this.onERC721Received.selector;
    }

    function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata)
        external
        pure
        returns (bytes4)
    {
        return this.onERC1155BatchReceived.selector;
    }
}

File 7 of 17 : KernelStorage.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Importing necessary interfaces
import {IEntryPoint} from "I4337/interfaces/IEntryPoint.sol";
import {IKernelValidator} from "../interfaces/IKernelValidator.sol";
import {IKernel} from "../interfaces/IKernel.sol";
import {KERNEL_STORAGE_SLOT, KERNEL_STORAGE_SLOT_1, IMPLEMENTATION_SLOT} from "../common/Constants.sol";
import {ExecutionDetail, WalletKernelStorage} from "../common/Structs.sol";
import {ValidUntil, ValidAfter} from "../common/Types.sol";

/// @title Kernel Storage Contract
/// @author taek<[email protected]>
/// @notice This contract serves as the storage module for the Kernel contract.
/// @dev This contract should only be used by the main Kernel contract.
abstract contract KernelStorage is IKernel {
    IEntryPoint public immutable entryPoint; // The entry point of the contract

    // Modifier to check if the function is called by the entry point, the contract itself or the owner
    modifier onlyFromEntryPointOrSelf() {
        if (msg.sender != address(entryPoint) && msg.sender != address(this)) {
            revert NotAuthorizedCaller();
        }
        _;
    }

    /// @param _entryPoint The address of the EntryPoint contract
    /// @dev Sets up the EntryPoint contract address
    constructor(IEntryPoint _entryPoint) {
        entryPoint = _entryPoint;
        getKernelStorage().defaultValidator = IKernelValidator(address(1));
    }

    // Function to initialize the wallet kernel
    function initialize(IKernelValidator _defaultValidator, bytes calldata _data) external payable override {
        _setInitialData(_defaultValidator, _data);
    }

    // Function to get the wallet kernel storage
    function getKernelStorage() internal pure returns (WalletKernelStorage storage ws) {
        assembly {
            ws.slot := KERNEL_STORAGE_SLOT
        }
    }

    // Function to upgrade the contract to a new implementation
    function upgradeTo(address _newImplementation) external payable override onlyFromEntryPointOrSelf {
        assembly {
            sstore(IMPLEMENTATION_SLOT, _newImplementation)
        }
        emit Upgraded(_newImplementation);
    }

    // Functions to get the nonce from the entry point
    function getNonce() external view virtual returns (uint256) {
        return entryPoint.getNonce(address(this), 0);
    }

    function getNonce(uint192 key) external view virtual returns (uint256) {
        return entryPoint.getNonce(address(this), key);
    }

    // query storage
    function getDefaultValidator() external view override returns (IKernelValidator validator) {
        assembly {
            validator := shr(80, sload(KERNEL_STORAGE_SLOT_1))
        }
    }

    function getDisabledMode() external view override returns (bytes4 disabled) {
        assembly {
            disabled := shl(224, sload(KERNEL_STORAGE_SLOT_1))
        }
    }

    function getLastDisabledTime() external view override returns (uint48) {
        return getKernelStorage().lastDisabledTime;
    }

    function getExecution(bytes4 _selector) external view override returns (ExecutionDetail memory) {
        return getKernelStorage().execution[_selector];
    }

    function setExecution(
        bytes4 _selector,
        address _executor,
        IKernelValidator _validator,
        ValidUntil _validUntil,
        ValidAfter _validAfter,
        bytes calldata _enableData
    ) external payable override onlyFromEntryPointOrSelf {
        getKernelStorage().execution[_selector] = ExecutionDetail({
            executor: _executor,
            validator: _validator,
            validUntil: _validUntil,
            validAfter: _validAfter
        });
        _validator.enable(_enableData);
        emit ExecutionChanged(_selector, _executor, address(_validator));
    }

    function setDefaultValidator(IKernelValidator _defaultValidator, bytes calldata _data)
        external
        payable
        virtual
        onlyFromEntryPointOrSelf
    {
        IKernelValidator oldValidator = getKernelStorage().defaultValidator;
        getKernelStorage().defaultValidator = _defaultValidator;
        emit DefaultValidatorChanged(address(oldValidator), address(_defaultValidator));
        _defaultValidator.enable(_data);
    }

    function disableMode(bytes4 _disableFlag) external payable override onlyFromEntryPointOrSelf {
        getKernelStorage().disabledMode = _disableFlag;
        getKernelStorage().lastDisabledTime = uint48(block.timestamp);
    }

    function _setInitialData(IKernelValidator _defaultValidator, bytes calldata _data) internal virtual {
        address validator;
        assembly {
            validator := shr(80, sload(KERNEL_STORAGE_SLOT_1))
        }
        if (address(validator) != address(0)) {
            revert AlreadyInitialized();
        }
        getKernelStorage().defaultValidator = _defaultValidator;
        _defaultValidator.enable(_data);
    }
}

File 8 of 17 : KernelHelper.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {SIG_VALIDATION_FAILED_UINT} from "../common/Constants.sol";
import {ValidationData} from "../common/Types.sol";

function _intersectValidationData(ValidationData a, ValidationData b) pure returns (ValidationData validationData) {
    assembly {
        // xor(a,b) == shows only matching bits
        // and(xor(a,b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) == filters out the validAfter and validUntil bits
        // if the result is not zero, then aggregator part is not matching
        // validCase :
        // a == 0 || b == 0 || xor(a,b) == 0
        // invalidCase :
        // a mul b != 0 && xor(a,b) != 0
        let sum := shl(96, add(a, b))
        switch or(
            iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)),
            or(eq(sum, shl(96, a)), eq(sum, shl(96, b)))
        )
        case 1 {
            validationData := and(or(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)
            // validAfter
            let a_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, a)
            let b_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, b)
            validationData := or(validationData, xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd))))
            // validUntil
            a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a)
            if iszero(a_vd) { a_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 }
            b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b)
            if iszero(b_vd) { b_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 }
            let until := xor(a_vd, mul(xor(a_vd, b_vd), lt(b_vd, a_vd)))
            if iszero(until) { until := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 }
            validationData := or(validationData, until)
        }
        default { validationData := SIG_VALIDATION_FAILED_UINT }
    }
}

File 9 of 17 : IKernelValidator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {UserOperation} from "I4337/interfaces/UserOperation.sol";
import "../common/Types.sol";

interface IKernelValidator {
    error NotImplemented();

    function enable(bytes calldata _data) external payable;

    function disable(bytes calldata _data) external payable;

    function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingFunds)
        external
        payable
        returns (ValidationData);

    function validateSignature(bytes32 hash, bytes calldata signature) external view returns (ValidationData);

    function validCaller(address caller, bytes calldata data) external view returns (bool);
}

// 3 modes
// 1. default mode, use preset validator for the kernel
// 2. enable mode, enable a new validator for given action and use it for current userOp
// 3. sudo mode, use default plugin for current userOp

File 10 of 17 : Constants.sol
pragma solidity ^0.8.0;

import {ValidationData} from "./Types.sol";

// Constants for kernel metadata
string constant KERNEL_NAME = "Kernel";
string constant KERNEL_VERSION = "0.2.4";

// ERC4337 constants
uint256 constant SIG_VALIDATION_FAILED_UINT = 1;
ValidationData constant SIG_VALIDATION_FAILED = ValidationData.wrap(SIG_VALIDATION_FAILED_UINT);

// STRUCT_HASH

/// @dev Struct hash for the ValidatorApproved struct -> keccak256("ValidatorApproved(bytes4 sig,uint256 validatorData,address executor,bytes enableData)")
bytes32 constant VALIDATOR_APPROVED_STRUCT_HASH = 0x3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee964176;

/* -------------------------------------------------------------------------- */
/*                                Storage slots                               */
/* -------------------------------------------------------------------------- */

/// @dev Storage slot for the kernel storage
bytes32 constant KERNEL_STORAGE_SLOT = 0x439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd8;
/// @dev Storage pointer inside the kernel storage, with 1 offset, to access directly disblaedMode, disabled date and default validator
bytes32 constant KERNEL_STORAGE_SLOT_1 = 0x439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd9;
/// @dev Storage slot for the logic implementation address
bytes32 constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

File 11 of 17 : Enums.sol
pragma solidity ^0.8.0;

enum Operation {
    Call,
    DelegateCall
}

enum ParamCondition {
    EQUAL,
    GREATER_THAN,
    LESS_THAN,
    GREATER_THAN_OR_EQUAL,
    LESS_THAN_OR_EQUAL,
    NOT_EQUAL
}

File 12 of 17 : Structs.sol
pragma solidity ^0.8.0;

import {IKernelValidator} from "../interfaces/IKernelValidator.sol";
import {ParamCondition, Operation} from "./Enums.sol";
import {ValidAfter, ValidUntil} from "./Types.sol";

// Defining a struct for execution details
struct ExecutionDetail {
    ValidAfter validAfter; // Until what time is this execution valid
    ValidUntil validUntil; // After what time is this execution valid
    address executor; // Who is the executor of this execution
    IKernelValidator validator; // The validator for this execution
}

struct Call {
    address to;
    uint256 value;
    bytes data;
}

// Defining a struct for wallet kernel storage
struct WalletKernelStorage {
    bytes32 __deprecated; // A deprecated field
    bytes4 disabledMode; // Mode which is currently disabled
    uint48 lastDisabledTime; // Last time when a mode was disabled
    IKernelValidator defaultValidator; // Default validator for the wallet
    mapping(bytes4 => ExecutionDetail) execution; // Mapping of function selectors to execution details
}

// Param Rule for session key
struct Nonces {
    uint128 lastNonce;
    uint128 invalidNonce;
}

struct ParamRule {
    uint256 offset;
    ParamCondition condition;
    bytes32 param;
}

struct ExecutionRule {
    ValidAfter validAfter; // 48 bits
    uint48 interval; // 48 bits
    uint48 runs; // 48 bits
}

struct ExecutionStatus {
    ValidAfter validAfter; // 48 bits
    uint48 runs; // 48 bits
}

struct Permission {
    uint32 index;
    address target;
    bytes4 sig;
    uint256 valueLimit;
    ParamRule[] rules;
    ExecutionRule executionRule;
    Operation operation;
}

struct SessionData {
    bytes32 merkleRoot;
    ValidAfter validAfter;
    ValidUntil validUntil;
    address paymaster; // address(0) means accept userOp without paymaster, address(1) means reject userOp with paymaster, other address means accept userOp with paymaster with the address
    uint256 nonce;
}

File 13 of 17 : Types.sol
pragma solidity ^0.8.9;

type ValidAfter is uint48;

type ValidUntil is uint48;

type ValidationData is uint256;

function packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure returns (ValidationData) {
    return ValidationData.wrap(
        uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160
    );
}

function packValidationData(address aggregator, ValidAfter validAfter, ValidUntil validUntil)
    pure
    returns (ValidationData)
{
    return ValidationData.wrap(
        uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160
            | uint160(aggregator)
    );
}

function parseValidationData(ValidationData validationData)
    pure
    returns (ValidAfter validAfter, ValidUntil validUntil, address result)
{
    assembly {
        result := validationData
        validUntil := and(shr(160, validationData), 0xffffffffffff)
        switch iszero(validUntil)
        case 1 { validUntil := 0xffffffffffff }
        validAfter := shr(208, validationData)
    }
}

File 14 of 17 : IStakeManager.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.12;

/**
 * Manage deposits and stakes.
 * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).
 * Stake is value locked for at least "unstakeDelay" by the staked entity.
 */
interface IStakeManager {
    event Deposited(address indexed account, uint256 totalDeposit);

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

    // Emitted when stake or unstake delay are modified.
    event StakeLocked(
        address indexed account,
        uint256 totalStaked,
        uint256 unstakeDelaySec
    );

    // Emitted once a stake is scheduled for withdrawal.
    event StakeUnlocked(address indexed account, uint256 withdrawTime);

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

    /**
     * @param deposit         - The entity's deposit.
     * @param staked          - True if this entity is staked.
     * @param stake           - Actual amount of ether staked for this entity.
     * @param unstakeDelaySec - Minimum delay to withdraw the stake.
     * @param withdrawTime    - First block timestamp where 'withdrawStake' will be callable, or zero if already locked.
     * @dev Sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)
     *      and the rest fit into a 2nd cell.
     *      - 112 bit allows for 10^15 eth
     *      - 48 bit for full timestamp
     *      - 32 bit allows 150 years for unstake delay
     */
    struct DepositInfo {
        uint112 deposit;
        bool staked;
        uint112 stake;
        uint32 unstakeDelaySec;
        uint48 withdrawTime;
    }

    // API struct used by getStakeInfo and simulateValidation.
    struct StakeInfo {
        uint256 stake;
        uint256 unstakeDelaySec;
    }

    /**
     * Get deposit info.
     * @param account - The account to query.
     * @return info   - Full deposit information of given account.
     */
    function getDepositInfo(
        address account
    ) external view returns (DepositInfo memory info);

    /**
     * Get account balance.
     * @param account - The account to query.
     * @return        - The deposit (for gas payment) of the account.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * Add to the deposit of the given account.
     * @param account - The account to add to.
     */
    function depositTo(address account) external payable;

    /**
     * Add to the account's stake - amount and delay
     * any pending unstake is first cancelled.
     * @param _unstakeDelaySec - The new lock duration before the deposit can be withdrawn.
     */
    function addStake(uint32 _unstakeDelaySec) external payable;

    /**
     * Attempt to unlock the stake.
     * The value can be withdrawn (using withdrawStake) after the unstake delay.
     */
    function unlockStake() external;

    /**
     * Withdraw from the (unlocked) stake.
     * Must first call unlockStake and wait for the unstakeDelay to pass.
     * @param withdrawAddress - The address to send withdrawn value.
     */
    function withdrawStake(address payable withdrawAddress) external;

    /**
     * Withdraw from the deposit.
     * @param withdrawAddress - The address to send withdrawn value.
     * @param withdrawAmount  - The amount to withdraw.
     */
    function withdrawTo(
        address payable withdrawAddress,
        uint256 withdrawAmount
    ) external;
}

File 15 of 17 : IAggregator.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;

import "./UserOperation.sol";

/**
 * Aggregated Signatures validator.
 */
interface IAggregator {
    /**
     * Validate aggregated signature.
     * Revert if the aggregated signature does not match the given list of operations.
     * @param userOps   - Array of UserOperations to validate the signature for.
     * @param signature - The aggregated signature.
     */
    function validateSignatures(
        UserOperation[] calldata userOps,
        bytes calldata signature
    ) external view;

    /**
     * Validate signature of a single userOp.
     * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation
     * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.
     * @param userOp        - The userOperation received from the user.
     * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps.
     *                        (usually empty, unless account and aggregator support some kind of "multisig".
     */
    function validateUserOpSignature(
        UserOperation calldata userOp
    ) external view returns (bytes memory sigForUserOp);

    /**
     * Aggregate multiple signatures into a single value.
     * This method is called off-chain to calculate the signature to pass with handleOps()
     * bundler MAY use optimized custom code perform this aggregation.
     * @param userOps              - Array of UserOperations to collect the signatures from.
     * @return aggregatedSignature - The aggregated signature.
     */
    function aggregateSignatures(
        UserOperation[] calldata userOps
    ) external view returns (bytes memory aggregatedSignature);
}

File 16 of 17 : INonceManager.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;

interface INonceManager {

    /**
     * Return the next nonce for this sender.
     * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)
     * But UserOp with different keys can come with arbitrary order.
     *
     * @param sender the account address
     * @param key the high 192 bit of the nonce
     * @return nonce a full nonce to pass for next UserOp with this sender.
     */
    function getNonce(address sender, uint192 key)
    external view returns (uint256 nonce);

    /**
     * Manually increment the nonce of the sender.
     * This method is exposed just for completeness..
     * Account does NOT need to call it, neither during validation, nor elsewhere,
     * as the EntryPoint will update the nonce regardless.
     * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future
     * UserOperations will not pay extra for the first transaction with a given key.
     */
    function incrementNonce(uint192 key) external;
}

File 17 of 17 : IKernel.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import {IKernelValidator} from "./IKernelValidator.sol";
import {ExecutionDetail, Call} from "../common/Structs.sol";
import {ValidationData, ValidUntil, ValidAfter} from "../common/Types.sol";
import {Operation} from "../common/Enums.sol";
import {UserOperation} from "I4337/interfaces/UserOperation.sol";

interface IKernel {
    // Event declarations
    event Upgraded(address indexed newImplementation);

    event DefaultValidatorChanged(address indexed oldValidator, address indexed newValidator);

    event ExecutionChanged(bytes4 indexed selector, address indexed executor, address indexed validator);

    // Error declarations
    error NotAuthorizedCaller();

    error AlreadyInitialized();

    error NotEntryPoint();

    error DisabledMode();

    error DeprecatedOperation();

    function initialize(IKernelValidator _validator, bytes calldata _data) external payable;

    function upgradeTo(address _newImplementation) external payable;

    function getNonce() external view returns (uint256);

    function getNonce(uint192 key) external view returns (uint256);

    function getDefaultValidator() external view returns (IKernelValidator);

    function getDisabledMode() external view returns (bytes4 disabled);

    function getLastDisabledTime() external view returns (uint48);

    /// @notice Returns the execution details for a specific function signature
    /// @dev This function can be used to get execution details for a specific function signature
    /// @param _selector The function signature
    /// @return ExecutionDetail struct containing the execution details
    function getExecution(bytes4 _selector) external view returns (ExecutionDetail memory);

    /// @notice Changes the execution details for a specific function selector
    /// @dev This function can only be called from the EntryPoint contract, the contract owner, or itself
    /// @param _selector The selector of the function for which execution details are being set
    /// @param _executor The executor to be associated with the function selector
    /// @param _validator The validator contract that will be responsible for validating operations associated with this function selector
    /// @param _validUntil The timestamp until which the execution details are valid
    /// @param _validAfter The timestamp after which the execution details are valid
    function setExecution(
        bytes4 _selector,
        address _executor,
        IKernelValidator _validator,
        ValidUntil _validUntil,
        ValidAfter _validAfter,
        bytes calldata _enableData
    ) external payable;

    function setDefaultValidator(IKernelValidator _defaultValidator, bytes calldata _data) external payable;

    /// @notice Updates the disabled mode
    /// @dev This function can be used to update the disabled mode
    /// @param _disableFlag The new disabled mode
    function disableMode(bytes4 _disableFlag) external payable;

    /// @notice Executes a function call to an external contract
    /// @dev The type of operation (call or delegatecall) is specified as an argument.
    /// @param to The address of the target contract
    /// @param value The amount of Ether to send
    /// @param data The call data to be sent
    /// operation deprecated operation type, usere executeBatch for batch operation
    function execute(address to, uint256 value, bytes memory data, Operation) external payable;

    function executeBatch(Call[] memory calls) external payable;

    function executeDelegateCall(address to, bytes memory data) external payable;

    /// @notice Validates a user operation based on its mode
    /// @dev This function will validate user operation and be called by EntryPoint
    /// @param userOp The user operation to be validated
    /// @param userOpHash The hash of the user operation
    /// @param missingAccountFunds The funds needed to be reimbursed
    /// @return validationData The data used for validation
    function validateUserOp(UserOperation memory userOp, bytes32 userOpHash, uint256 missingAccountFunds)
        external
        payable
        returns (ValidationData validationData);
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "solady/=lib/solady/src/",
    "I4337/=lib/I4337/src/",
    "FreshCryptoLib/=lib/FreshCryptoLib/solidity/src/",
    "p256-verifier/=lib/p256-verifier/src/",
    "@openzeppelin/contracts/=lib/p256-verifier/lib/openzeppelin-contracts/contracts/",
    "account-abstraction/=lib/account-abstraction/contracts/",
    "erc4626-tests/=lib/p256-verifier/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": false
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"contract IEntryPoint","name":"_entryPoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"DeprecatedOperation","type":"error"},{"inputs":[],"name":"DisabledMode","type":"error"},{"inputs":[],"name":"NotAuthorizedCaller","type":"error"},{"inputs":[],"name":"NotEntryPoint","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldValidator","type":"address"},{"indexed":true,"internalType":"address","name":"newValidator","type":"address"}],"name":"DefaultValidatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":true,"internalType":"address","name":"validator","type":"address"}],"name":"ExecutionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes4","name":"_disableFlag","type":"bytes4"}],"name":"disableMode","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":[],"name":"entryPoint","outputs":[{"internalType":"contract IEntryPoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Operation","name":"_operation","type":"uint8"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"}],"name":"executeBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"executeDelegateCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getDefaultValidator","outputs":[{"internalType":"contract IKernelValidator","name":"validator","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDisabledMode","outputs":[{"internalType":"bytes4","name":"disabled","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_selector","type":"bytes4"}],"name":"getExecution","outputs":[{"components":[{"internalType":"ValidAfter","name":"validAfter","type":"uint48"},{"internalType":"ValidUntil","name":"validUntil","type":"uint48"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"contract IKernelValidator","name":"validator","type":"address"}],"internalType":"struct ExecutionDetail","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastDisabledTime","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint192","name":"key","type":"uint192"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IKernelValidator","name":"_defaultValidator","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract IKernelValidator","name":"_defaultValidator","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"setDefaultValidator","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_selector","type":"bytes4"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"contract IKernelValidator","name":"_validator","type":"address"},{"internalType":"ValidUntil","name":"_validUntil","type":"uint48"},{"internalType":"ValidAfter","name":"_validAfter","type":"uint48"},{"internalType":"bytes","name":"_enableData","type":"bytes"}],"name":"setExecution","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"validateSignature","outputs":[{"internalType":"ValidationData","name":"","type":"uint256"}],"stateMutability":"view","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":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"_userOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"missingAccountFunds","type":"uint256"}],"name":"validateUserOp","outputs":[{"internalType":"ValidationData","name":"validationData","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101406040523480156200001257600080fd5b5060405162002c4738038062002c47833981016040819052620000359162000137565b306080524660a0528060608062000081604080518082018252600681526512d95c9b995b60d21b602080830191909152825180840190935260058352640c0b8c8b8d60da1b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152938401929092529082015246606082015230608082015260a090206101005250506001600160a01b031661012052507f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd98054600160501b600160f01b0319166a010000000000000000000017905562000169565b6000602082840312156200014a57600080fd5b81516001600160a01b03811681146200016257600080fd5b9392505050565b60805160a05160c05160e0516101005161012051612a4162000206600039600081816101e9015281816105ec015281816108e201528181610ae401528181610bbf01528181610c7301528181610f8301528181611007015281816110bf0152818161120a015281816112a3015261133101526000611c6f01526000611d2901526000611d0301526000611cb301526000611c900152612a416000f3fe60806040526004361061014f5760003560e01c806354fd4d50116100b6578063b68df16d1161006f578063b68df16d1461060e578063bc197c8114610621578063d087d28814610650578063d1f5789414610665578063d541622114610678578063f23a6e611461068b5761018e565b806354fd4d501461050557806355b14f501461053657806357b750471461054957806384b0196e1461056e57806388e7fd0614610596578063b0d691fe146105da5761018e565b806334fcd5be1161010857806334fcd5be146103885780633659cfe61461039b5780633a871cdd146103ae5780633e1b0812146103c157806351166ba0146103e157806351945447146104f25761018e565b806306fdde03146102615780630b3dc354146102a9578063150b7a02146102e25780631626ba7e1461032757806329f8b17414610347578063333daf921461035a5761018e565b3661018e57604080513381523460208201527f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f88525874910160405180910390a1005b600080356001600160e01b031916905060006101b5600080516020612a0183398151915290565b6001600160e01b0319831660009081526002919091016020526040902054600160601b90046001600160a01b0390811691507f000000000000000000000000000000000000000000000000000000000000000016331480159061021d575061021b6106b8565b155b1561023b57604051637046c88d60e01b815260040160405180910390fd5b3660008037600080366000845af43d6000803e80801561025a573d6000f35b3d6000fd5b005b34801561026d57600080fd5b506102936040518060400160405280600681526020016512d95c9b995b60d21b81525081565b6040516102a09190611dd5565b60405180910390f35b3480156102b557600080fd5b50600080516020612a218339815191525460501c5b6040516001600160a01b0390911681526020016102a0565b3480156102ee57600080fd5b5061030e6102fd366004611e58565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016102a0565b34801561033357600080fd5b5061030e610342366004611eca565b6107fe565b61025f610355366004611f41565b6108d7565b34801561036657600080fd5b5061037a610375366004611eca565b610ac2565b6040519081526020016102a0565b61025f6103963660046120df565b610ad9565b61025f6103a93660046121e5565b610bb4565b61037a6103bc366004612202565b610c66565b3480156103cd57600080fd5b5061037a6103dc366004612255565b610f5c565b3480156103ed57600080fd5b506104a56103fc36600461227e565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160e01b03199590951681527f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda855283902083519182018452805465ffffffffffff8082168452600160301b82041695830195909552600160601b9094046001600160a01b03908116938201939093526001909301549091169082015290565b60408051825165ffffffffffff908116825260208085015190911690820152828201516001600160a01b0390811692820192909252606092830151909116918101919091526080016102a0565b61025f610500366004612299565b610ffc565b34801561051157600080fd5b50610293604051806040016040528060058152602001640c0b8c8b8d60da1b81525081565b61025f610544366004612308565b6110b4565b34801561055557600080fd5b50600080516020612a218339815191525460e01b61030e565b34801561057a57600080fd5b506105836111d8565b6040516102a09796959493929190612343565b3480156105a257600080fd5b50600080516020612a2183398151915254640100000000900465ffffffffffff1660405165ffffffffffff90911681526020016102a0565b3480156105e657600080fd5b506102ca7f000000000000000000000000000000000000000000000000000000000000000081565b61025f61061c3660046123d9565b6111ff565b34801561062d57600080fd5b5061030e61063c36600461246c565b63bc197c8160e01b98975050505050505050565b34801561065c57600080fd5b5061037a611284565b61025f610673366004612308565b61131b565b61025f61068636600461227e565b611326565b34801561069757600080fd5b5061030e6106a636600461252a565b63f23a6e6160e01b9695505050505050565b60006106c6336000366113bc565b156106d15750600190565b600080356001600160e01b031916905060006106f8600080516020612a0183398151915290565b6001600160e01b0319831660009081526002919091016020526040902060018101549091506001600160a01b0316158061075c57508054600160301b900465ffffffffffff161580159061075c5750805442600160301b90910465ffffffffffff16105b80610771575080544265ffffffffffff909116115b1561077f5760009250505090565b6001810154604051639ea9bd5960e01b81526001600160a01b0390911690639ea9bd59906107b690339060009036906004016125ce565b602060405180830381865afa1580156107d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f791906125f3565b9250505090565b60008061080961144d565b60405161190160f01b60208201526022810182905260428101879052909150600090606201604051602081830303815290604052805190602001209050600061085533838989896114d0565b905060008060006108658461164b565b925092509250428365ffffffffffff161115801561088b5750428265ffffffffffff1610155b801561089e57506001600160a01b038116155b156108b95750630b135d3f60e11b95506108d0945050505050565b506001600160e01b031995506108d0945050505050565b9392505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906109105750333014155b1561092e57604051637046c88d60e01b815260040160405180910390fd5b60405180608001604052808465ffffffffffff1681526020018565ffffffffffff168152602001876001600160a01b03168152602001866001600160a01b0316815250610986600080516020612a0183398151915290565b6001600160e01b031989166000908152600291909101602090815260409182902083518154928501518585015165ffffffffffff9283166001600160601b031990951694909417600160301b9290911691909102176bffffffffffffffffffffffff16600160601b6001600160a01b0393841602178155606090930151600190930180546001600160a01b031916938216939093179092555163064acaab60e11b815290861690630c95955690610a439085908590600401612615565b600060405180830381600087803b158015610a5d57600080fd5b505af1158015610a71573d6000803e3d6000fd5b50506040516001600160a01b038089169350891691506001600160e01b03198a16907fed03d2572564284398470d3f266a693e29ddfff3eba45fc06c5e91013d32135390600090a450505050505050565b6000610ad133858686866114d0565b949350505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590610b175750610b156106b8565b155b15610b3557604051637046c88d60e01b815260040160405180910390fd5b805160005b81811015610baf576000838281518110610b5657610b56612629565b6020026020010151905060008160000151905060008260200151905060008360400151905060008082516020840185875af1808015610b9a57600187019650610ba4565b3d6000803e3d6000fd5b505050505050610b3a565b505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590610bed5750333014155b15610c0b57604051637046c88d60e01b815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8190556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cb157604051636b31ba1560e11b815260040160405180910390fd5b6024600480356101448101358101838101939083013592910190600090610cda9082858761263f565b610ce391612669565b90506001600160e01b03198116600003610d1d578515610d07573434343489335af1505b610d1288888861167e565b9450505050506108d0565b600080516020612a218339815191525460e01b81811615610d465763fc2f51c56000526004601cfd5b5060006001600160e01b03198216600160e01b03610e155760408301358301601f1981013560007f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda81610d9c600482868861263f565b610da591612669565b6001600160e01b0319168152602081019190915260400160002060018101546001600160a01b031694509050610dde876004818b61263f565b82549199509750600160301b810460a01b65ffffffffffff60a01b1660d09190911b6001600160d01b031916179850505050610e77565b6001600160e01b03198216600160e11b03610e695760408301358301601f19810135610e58610e4860046000848661263f565b610e5191612669565b8888611776565b919a50985096509250610e77915050565b6001955050505050506108d0565b8615610e8757343434348a335af1505b6000610e928a612697565b905085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610140820152604051633a871cdd60e01b8152610f4e9088906001600160a01b03851690633a871cdd90610f069086908f908f906004016127a5565b6020604051808303816000875af1158015610f25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f499190612897565b611adf565b9a9950505050505050505050565b604051631aab3f0d60e11b81523060048201526001600160c01b03821660248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906335567e1a90604401602060405180830381865afa158015610fd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff69190612897565b92915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906110355750333014155b801561104657506110446106b8565b155b1561106457604051637046c88d60e01b815260040160405180910390fd5b6000816001811115611078576110786128b0565b14611096576040516367ce775960e01b815260040160405180910390fd5b60008083516020850186885af13d6000803e80801561025a573d6000f35b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906110ed5750333014155b1561110b57604051637046c88d60e01b815260040160405180910390fd5b600080516020612a2183398151915280546001600160a01b03858116600160501b818102600160501b600160f01b031985161790945560405193909204169182907fa35f5cdc5fbabb614b4cd5064ce5543f43dc8fab0e4da41255230eb8aba2531c90600090a360405163064acaab60e11b81526001600160a01b03851690630c959556906111a09086908690600401612615565b600060405180830381600087803b1580156111ba57600080fd5b505af11580156111ce573d6000803e3d6000fd5b5050505050505050565b600f60f81b60608060008080836111ed611b9d565b97989097965046955030945091925090565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906112385750333014155b801561124957506112476106b8565b155b1561126757604051637046c88d60e01b815260040160405180910390fd5b600080825160208401855af43d6000803e80801561025a573d6000f35b604051631aab3f0d60e11b8152306004820152600060248201819052907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906335567e1a90604401602060405180830381865afa1580156112f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113169190612897565b905090565b610baf838383611bd9565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480159061135f5750333014155b1561137d57604051637046c88d60e01b815260040160405180910390fd5b600080516020612a21833981519152805460e09290921c69ffffffffffffffffffff19909216919091176401000000004265ffffffffffff1602179055565b600080516020612a2183398151915254604051639ea9bd5960e01b815260009160501c906001600160a01b03821690639ea9bd5990611403908890889088906004016125ce565b602060405180830381865afa158015611420573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144491906125f3565b95945050505050565b600080600061145a611b9d565b8151602092830120815191830191909120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818601528082019390935260608301919091524660808301523060a0808401919091528151808403909101815260c0909201905280519101209392505050565b600080600080516020612a218339815191525460501c9050600080826001600160a01b031663333daf9260e01b898888604051602401611512939291906128c6565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199095169490941790935251611554928b918e91016128e0565b60408051601f198184030181529082905261156e91612914565b600060405180830381855afa9150503d80600081146115a9576040519150601f19603f3d011682016040523d82523d6000602084013e6115ae565b606091505b50915091508161162a5760405162461bcd60e51b815260206004820152603860248201527f4b65726e656c3a3a5f76616c69646174655369676e61747572653a206661696c60448201527f656420746f2076616c6964617465207369676e61747572650000000000000000606482015260840160405180910390fd5b8080602001905181019061163e9190612897565b9998505050505050505050565b600060a082901c65ffffffffffff1682811560001981016116705765ffffffffffff92505b508360d01c92509193909250565b60008061168a85612697565b905061169a610140860186612930565b6116a891600490829061263f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610140820152600080516020612a2183398151915254604051633a871cdd60e01b815260509190911c906001600160a01b03821690633a871cdd90611729908590899089906004016127a5565b6020604051808303816000875af1158015611748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176c9190612897565b9695505050505050565b600080368161178960246010878961263f565b61179291612976565b60601c9350605860006117a8826038898b61263f565b6117b1916129a4565b828101929091508801816117ca60208501858b8d61263f565b6117d3916129a4565b60001c925060208401935060006118bd7f3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee96417660001b8d8d8d60049060249261181c9392919061263f565b611825916129a4565b60001c8e8e60249060389261183c9392919061263f565b61184591612976565b60601c87876040516118589291906129c2565b6040519081900381206118a295949392916020019485526001600160e01b031993909316602085015260408401919091526001600160a01b03166060830152608082015260a00190565b60405160208183030381529060405280519060200120611c6d565b905061190d6118e13083848f8f8b908b8d01926118dc9392919061263f565b6114d0565b8c8c6004906024926118f59392919061263f565b6118fe916129a4565b6001600160a01b031916611adf565b97508385019450848b019650848a03955060405180608001604052808c8c600490600a9261193d9392919061263f565b611946916129d2565b60d01c65ffffffffffff1681526020018c8c600a9060109261196a9392919061263f565b611973916129d2565b60d01c65ffffffffffff1681526020018c8c6024906038926119979392919061263f565b6119a091612976565b60601c6001600160a01b031681526020018c8c6010906024926119c59392919061263f565b6119ce91612976565b60601c9052600080516020612a018339815191526001600160e01b03198e166000908152600291909101602090815260409182902083518154928501518585015165ffffffffffff9283166001600160601b031990951694909417600160301b9290911691909102176bffffffffffffffffffffffff16600160601b6001600160a01b0393841602178155606090930151600190930180546001600160a01b031916938216939093179092555163064acaab60e11b8152908a1690630c95955690611a9f9086908690600401612615565b600060405180830381600087803b158015611ab957600080fd5b505af1158015611acd573d6000803e3d6000fd5b50505050505050505093509350935093565b600081830160601b8260601b81148460601b8214176001600160a01b0384861816151760018114611b135760019250611b95565b6001600160d01b031980851690861681811881831102188686176001600160a01b031617935065ffffffffffff60a01b86169081611b585765ffffffffffff60a01b91505b5065ffffffffffff60a01b851680611b76575065ffffffffffff60a01b5b808218908211021880611b8f575065ffffffffffff60a01b5b92909217915b505092915050565b604080518082018252600681526512d95c9b995b60d21b602080830191909152825180840190935260058352640c0b8c8b8d60da1b9083015291565b600080516020612a218339815191525460501c6001600160a01b03811615611c135760405162dc149f60e41b815260040160405180910390fd5b600080516020612a218339815191528054600160501b600160f01b031916600160501b6001600160a01b0387169081029190911790915560405163064acaab60e11b8152630c959556906111a09086908690600401612615565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000030147f0000000000000000000000000000000000000000000000000000000000000000461416611d605750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b60005b83811015611da0578181015183820152602001611d88565b50506000910152565b60008151808452611dc1816020860160208601611d85565b601f01601f19169290920160200192915050565b6020815260006108d06020830184611da9565b6001600160a01b0381168114611dfd57600080fd5b50565b8035611e0b81611de8565b919050565b60008083601f840112611e2257600080fd5b5081356001600160401b03811115611e3957600080fd5b602083019150836020828501011115611e5157600080fd5b9250929050565b600080600080600060808688031215611e7057600080fd5b8535611e7b81611de8565b94506020860135611e8b81611de8565b93506040860135925060608601356001600160401b03811115611ead57600080fd5b611eb988828901611e10565b969995985093965092949392505050565b600080600060408486031215611edf57600080fd5b8335925060208401356001600160401b03811115611efc57600080fd5b611f0886828701611e10565b9497909650939450505050565b80356001600160e01b031981168114611e0b57600080fd5b65ffffffffffff81168114611dfd57600080fd5b600080600080600080600060c0888a031215611f5c57600080fd5b611f6588611f15565b96506020880135611f7581611de8565b95506040880135611f8581611de8565b94506060880135611f9581611f2d565b93506080880135611fa581611f2d565b925060a08801356001600160401b03811115611fc057600080fd5b611fcc8a828b01611e10565b989b979a50959850939692959293505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561201757612017611fdf565b60405290565b60405161016081016001600160401b038111828210171561201757612017611fdf565b604051601f8201601f191681016001600160401b038111828210171561206857612068611fdf565b604052919050565b600082601f83011261208157600080fd5b81356001600160401b0381111561209a5761209a611fdf565b6120ad601f8201601f1916602001612040565b8181528460208386010111156120c257600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156120f257600080fd5b82356001600160401b038082111561210957600080fd5b818501915085601f83011261211d57600080fd5b81358181111561212f5761212f611fdf565b8060051b61213e858201612040565b918252838101850191858101908984111561215857600080fd5b86860192505b8383101561163e578235858111156121765760008081fd5b86016060818c03601f190181131561218e5760008081fd5b612196611ff5565b898301356121a381611de8565b81526040838101358b8301529183013591888311156121c25760008081fd5b6121d08e8c85870101612070565b9082015284525050918601919086019061215e565b6000602082840312156121f757600080fd5b81356108d081611de8565b60008060006060848603121561221757600080fd5b83356001600160401b0381111561222d57600080fd5b8401610160818703121561224057600080fd5b95602085013595506040909401359392505050565b60006020828403121561226757600080fd5b81356001600160c01b03811681146108d057600080fd5b60006020828403121561229057600080fd5b6108d082611f15565b600080600080608085870312156122af57600080fd5b84356122ba81611de8565b93506020850135925060408501356001600160401b038111156122dc57600080fd5b6122e887828801612070565b9250506060850135600281106122fd57600080fd5b939692955090935050565b60008060006040848603121561231d57600080fd5b833561232881611de8565b925060208401356001600160401b03811115611efc57600080fd5b60ff60f81b881681526000602060e08184015261236360e084018a611da9565b8381036040850152612375818a611da9565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156123c7578351835292840192918401916001016123ab565b50909c9b505050505050505050505050565b600080604083850312156123ec57600080fd5b82356123f781611de8565b915060208301356001600160401b0381111561241257600080fd5b61241e85828601612070565b9150509250929050565b60008083601f84011261243a57600080fd5b5081356001600160401b0381111561245157600080fd5b6020830191508360208260051b8501011115611e5157600080fd5b60008060008060008060008060a0898b03121561248857600080fd5b883561249381611de8565b975060208901356124a381611de8565b965060408901356001600160401b03808211156124bf57600080fd5b6124cb8c838d01612428565b909850965060608b01359150808211156124e457600080fd5b6124f08c838d01612428565b909650945060808b013591508082111561250957600080fd5b506125168b828c01611e10565b999c989b5096995094979396929594505050565b60008060008060008060a0878903121561254357600080fd5b863561254e81611de8565b9550602087013561255e81611de8565b9450604087013593506060870135925060808701356001600160401b0381111561258757600080fd5b61259389828a01611e10565b979a9699509497509295939492505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038416815260406020820181905260009061144490830184866125a5565b60006020828403121561260557600080fd5b815180151581146108d057600080fd5b602081526000610ad16020830184866125a5565b634e487b7160e01b600052603260045260246000fd5b6000808585111561264f57600080fd5b8386111561265c57600080fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015611b955760049490940360031b84901b1690921692915050565b600061016082360312156126aa57600080fd5b6126b261201d565b6126bb83611e00565b81526020830135602082015260408301356001600160401b03808211156126e157600080fd5b6126ed36838701612070565b6040840152606085013591508082111561270657600080fd5b61271236838701612070565b60608401526080850135608084015260a085013560a084015260c085013560c084015260e085013560e0840152610100915081850135828401526101209150818501358181111561276257600080fd5b61276e36828801612070565b83850152506101409150818501358181111561278957600080fd5b61279536828801612070565b8385015250505080915050919050565b606081526127bf6060820185516001600160a01b03169052565b60208401516080820152600060408501516101608060a08501526127e76101c0850183611da9565b91506060870151605f19808685030160c08701526128058483611da9565b9350608089015160e087015260a08901519150610100828188015260c08a01519250610120838189015260e08b0151935061014084818a0152828c0151868a0152818c0151955083898803016101808a01526128618787611da9565b9650808c0151955050505080868503016101a087015250506128838282611da9565b602085019690965250505060400152919050565b6000602082840312156128a957600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b8381526040602082015260006114446040830184866125a5565b600084516128f2818460208901611d85565b919091019283525060601b6001600160601b0319166020820152603401919050565b60008251612926818460208701611d85565b9190910192915050565b6000808335601e1984360301811261294757600080fd5b8301803591506001600160401b0382111561296157600080fd5b602001915036819003821315611e5157600080fd5b6001600160601b03198135818116916014851015611b955760149490940360031b84901b1690921692915050565b80356020831015610ff657600019602084900360031b1b1692915050565b8183823760009101908152919050565b6001600160d01b03198135818116916006851015611b955760069490940360031b84901b169092169291505056fe439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd8439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd90000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789

Deployed Bytecode

0x60806040526004361061014f5760003560e01c806354fd4d50116100b6578063b68df16d1161006f578063b68df16d1461060e578063bc197c8114610621578063d087d28814610650578063d1f5789414610665578063d541622114610678578063f23a6e611461068b5761018e565b806354fd4d501461050557806355b14f501461053657806357b750471461054957806384b0196e1461056e57806388e7fd0614610596578063b0d691fe146105da5761018e565b806334fcd5be1161010857806334fcd5be146103885780633659cfe61461039b5780633a871cdd146103ae5780633e1b0812146103c157806351166ba0146103e157806351945447146104f25761018e565b806306fdde03146102615780630b3dc354146102a9578063150b7a02146102e25780631626ba7e1461032757806329f8b17414610347578063333daf921461035a5761018e565b3661018e57604080513381523460208201527f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f88525874910160405180910390a1005b600080356001600160e01b031916905060006101b5600080516020612a0183398151915290565b6001600160e01b0319831660009081526002919091016020526040902054600160601b90046001600160a01b0390811691507f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916331480159061021d575061021b6106b8565b155b1561023b57604051637046c88d60e01b815260040160405180910390fd5b3660008037600080366000845af43d6000803e80801561025a573d6000f35b3d6000fd5b005b34801561026d57600080fd5b506102936040518060400160405280600681526020016512d95c9b995b60d21b81525081565b6040516102a09190611dd5565b60405180910390f35b3480156102b557600080fd5b50600080516020612a218339815191525460501c5b6040516001600160a01b0390911681526020016102a0565b3480156102ee57600080fd5b5061030e6102fd366004611e58565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016102a0565b34801561033357600080fd5b5061030e610342366004611eca565b6107fe565b61025f610355366004611f41565b6108d7565b34801561036657600080fd5b5061037a610375366004611eca565b610ac2565b6040519081526020016102a0565b61025f6103963660046120df565b610ad9565b61025f6103a93660046121e5565b610bb4565b61037a6103bc366004612202565b610c66565b3480156103cd57600080fd5b5061037a6103dc366004612255565b610f5c565b3480156103ed57600080fd5b506104a56103fc36600461227e565b60408051608080820183526000808352602080840182905283850182905260609384018290526001600160e01b03199590951681527f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda855283902083519182018452805465ffffffffffff8082168452600160301b82041695830195909552600160601b9094046001600160a01b03908116938201939093526001909301549091169082015290565b60408051825165ffffffffffff908116825260208085015190911690820152828201516001600160a01b0390811692820192909252606092830151909116918101919091526080016102a0565b61025f610500366004612299565b610ffc565b34801561051157600080fd5b50610293604051806040016040528060058152602001640c0b8c8b8d60da1b81525081565b61025f610544366004612308565b6110b4565b34801561055557600080fd5b50600080516020612a218339815191525460e01b61030e565b34801561057a57600080fd5b506105836111d8565b6040516102a09796959493929190612343565b3480156105a257600080fd5b50600080516020612a2183398151915254640100000000900465ffffffffffff1660405165ffffffffffff90911681526020016102a0565b3480156105e657600080fd5b506102ca7f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278981565b61025f61061c3660046123d9565b6111ff565b34801561062d57600080fd5b5061030e61063c36600461246c565b63bc197c8160e01b98975050505050505050565b34801561065c57600080fd5b5061037a611284565b61025f610673366004612308565b61131b565b61025f61068636600461227e565b611326565b34801561069757600080fd5b5061030e6106a636600461252a565b63f23a6e6160e01b9695505050505050565b60006106c6336000366113bc565b156106d15750600190565b600080356001600160e01b031916905060006106f8600080516020612a0183398151915290565b6001600160e01b0319831660009081526002919091016020526040902060018101549091506001600160a01b0316158061075c57508054600160301b900465ffffffffffff161580159061075c5750805442600160301b90910465ffffffffffff16105b80610771575080544265ffffffffffff909116115b1561077f5760009250505090565b6001810154604051639ea9bd5960e01b81526001600160a01b0390911690639ea9bd59906107b690339060009036906004016125ce565b602060405180830381865afa1580156107d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f791906125f3565b9250505090565b60008061080961144d565b60405161190160f01b60208201526022810182905260428101879052909150600090606201604051602081830303815290604052805190602001209050600061085533838989896114d0565b905060008060006108658461164b565b925092509250428365ffffffffffff161115801561088b5750428265ffffffffffff1610155b801561089e57506001600160a01b038116155b156108b95750630b135d3f60e11b95506108d0945050505050565b506001600160e01b031995506108d0945050505050565b9392505050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916148015906109105750333014155b1561092e57604051637046c88d60e01b815260040160405180910390fd5b60405180608001604052808465ffffffffffff1681526020018565ffffffffffff168152602001876001600160a01b03168152602001866001600160a01b0316815250610986600080516020612a0183398151915290565b6001600160e01b031989166000908152600291909101602090815260409182902083518154928501518585015165ffffffffffff9283166001600160601b031990951694909417600160301b9290911691909102176bffffffffffffffffffffffff16600160601b6001600160a01b0393841602178155606090930151600190930180546001600160a01b031916938216939093179092555163064acaab60e11b815290861690630c95955690610a439085908590600401612615565b600060405180830381600087803b158015610a5d57600080fd5b505af1158015610a71573d6000803e3d6000fd5b50506040516001600160a01b038089169350891691506001600160e01b03198a16907fed03d2572564284398470d3f266a693e29ddfff3eba45fc06c5e91013d32135390600090a450505050505050565b6000610ad133858686866114d0565b949350505050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27891614801590610b175750610b156106b8565b155b15610b3557604051637046c88d60e01b815260040160405180910390fd5b805160005b81811015610baf576000838281518110610b5657610b56612629565b6020026020010151905060008160000151905060008260200151905060008360400151905060008082516020840185875af1808015610b9a57600187019650610ba4565b3d6000803e3d6000fd5b505050505050610b3a565b505050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27891614801590610bed5750333014155b15610c0b57604051637046c88d60e01b815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8190556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6000336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27891614610cb157604051636b31ba1560e11b815260040160405180910390fd5b6024600480356101448101358101838101939083013592910190600090610cda9082858761263f565b610ce391612669565b90506001600160e01b03198116600003610d1d578515610d07573434343489335af1505b610d1288888861167e565b9450505050506108d0565b600080516020612a218339815191525460e01b81811615610d465763fc2f51c56000526004601cfd5b5060006001600160e01b03198216600160e01b03610e155760408301358301601f1981013560007f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda81610d9c600482868861263f565b610da591612669565b6001600160e01b0319168152602081019190915260400160002060018101546001600160a01b031694509050610dde876004818b61263f565b82549199509750600160301b810460a01b65ffffffffffff60a01b1660d09190911b6001600160d01b031916179850505050610e77565b6001600160e01b03198216600160e11b03610e695760408301358301601f19810135610e58610e4860046000848661263f565b610e5191612669565b8888611776565b919a50985096509250610e77915050565b6001955050505050506108d0565b8615610e8757343434348a335af1505b6000610e928a612697565b905085858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610140820152604051633a871cdd60e01b8152610f4e9088906001600160a01b03851690633a871cdd90610f069086908f908f906004016127a5565b6020604051808303816000875af1158015610f25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f499190612897565b611adf565b9a9950505050505050505050565b604051631aab3f0d60e11b81523060048201526001600160c01b03821660248201526000907f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b0316906335567e1a90604401602060405180830381865afa158015610fd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff69190612897565b92915050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916148015906110355750333014155b801561104657506110446106b8565b155b1561106457604051637046c88d60e01b815260040160405180910390fd5b6000816001811115611078576110786128b0565b14611096576040516367ce775960e01b815260040160405180910390fd5b60008083516020850186885af13d6000803e80801561025a573d6000f35b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916148015906110ed5750333014155b1561110b57604051637046c88d60e01b815260040160405180910390fd5b600080516020612a2183398151915280546001600160a01b03858116600160501b818102600160501b600160f01b031985161790945560405193909204169182907fa35f5cdc5fbabb614b4cd5064ce5543f43dc8fab0e4da41255230eb8aba2531c90600090a360405163064acaab60e11b81526001600160a01b03851690630c959556906111a09086908690600401612615565b600060405180830381600087803b1580156111ba57600080fd5b505af11580156111ce573d6000803e3d6000fd5b5050505050505050565b600f60f81b60608060008080836111ed611b9d565b97989097965046955030945091925090565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278916148015906112385750333014155b801561124957506112476106b8565b155b1561126757604051637046c88d60e01b815260040160405180910390fd5b600080825160208401855af43d6000803e80801561025a573d6000f35b604051631aab3f0d60e11b8152306004820152600060248201819052907f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b0316906335567e1a90604401602060405180830381865afa1580156112f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113169190612897565b905090565b610baf838383611bd9565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789161480159061135f5750333014155b1561137d57604051637046c88d60e01b815260040160405180910390fd5b600080516020612a21833981519152805460e09290921c69ffffffffffffffffffff19909216919091176401000000004265ffffffffffff1602179055565b600080516020612a2183398151915254604051639ea9bd5960e01b815260009160501c906001600160a01b03821690639ea9bd5990611403908890889088906004016125ce565b602060405180830381865afa158015611420573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144491906125f3565b95945050505050565b600080600061145a611b9d565b8151602092830120815191830191909120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818601528082019390935260608301919091524660808301523060a0808401919091528151808403909101815260c0909201905280519101209392505050565b600080600080516020612a218339815191525460501c9050600080826001600160a01b031663333daf9260e01b898888604051602401611512939291906128c6565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199095169490941790935251611554928b918e91016128e0565b60408051601f198184030181529082905261156e91612914565b600060405180830381855afa9150503d80600081146115a9576040519150601f19603f3d011682016040523d82523d6000602084013e6115ae565b606091505b50915091508161162a5760405162461bcd60e51b815260206004820152603860248201527f4b65726e656c3a3a5f76616c69646174655369676e61747572653a206661696c60448201527f656420746f2076616c6964617465207369676e61747572650000000000000000606482015260840160405180910390fd5b8080602001905181019061163e9190612897565b9998505050505050505050565b600060a082901c65ffffffffffff1682811560001981016116705765ffffffffffff92505b508360d01c92509193909250565b60008061168a85612697565b905061169a610140860186612930565b6116a891600490829061263f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505050610140820152600080516020612a2183398151915254604051633a871cdd60e01b815260509190911c906001600160a01b03821690633a871cdd90611729908590899089906004016127a5565b6020604051808303816000875af1158015611748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176c9190612897565b9695505050505050565b600080368161178960246010878961263f565b61179291612976565b60601c9350605860006117a8826038898b61263f565b6117b1916129a4565b828101929091508801816117ca60208501858b8d61263f565b6117d3916129a4565b60001c925060208401935060006118bd7f3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee96417660001b8d8d8d60049060249261181c9392919061263f565b611825916129a4565b60001c8e8e60249060389261183c9392919061263f565b61184591612976565b60601c87876040516118589291906129c2565b6040519081900381206118a295949392916020019485526001600160e01b031993909316602085015260408401919091526001600160a01b03166060830152608082015260a00190565b60405160208183030381529060405280519060200120611c6d565b905061190d6118e13083848f8f8b908b8d01926118dc9392919061263f565b6114d0565b8c8c6004906024926118f59392919061263f565b6118fe916129a4565b6001600160a01b031916611adf565b97508385019450848b019650848a03955060405180608001604052808c8c600490600a9261193d9392919061263f565b611946916129d2565b60d01c65ffffffffffff1681526020018c8c600a9060109261196a9392919061263f565b611973916129d2565b60d01c65ffffffffffff1681526020018c8c6024906038926119979392919061263f565b6119a091612976565b60601c6001600160a01b031681526020018c8c6010906024926119c59392919061263f565b6119ce91612976565b60601c9052600080516020612a018339815191526001600160e01b03198e166000908152600291909101602090815260409182902083518154928501518585015165ffffffffffff9283166001600160601b031990951694909417600160301b9290911691909102176bffffffffffffffffffffffff16600160601b6001600160a01b0393841602178155606090930151600190930180546001600160a01b031916938216939093179092555163064acaab60e11b8152908a1690630c95955690611a9f9086908690600401612615565b600060405180830381600087803b158015611ab957600080fd5b505af1158015611acd573d6000803e3d6000fd5b50505050505050505093509350935093565b600081830160601b8260601b81148460601b8214176001600160a01b0384861816151760018114611b135760019250611b95565b6001600160d01b031980851690861681811881831102188686176001600160a01b031617935065ffffffffffff60a01b86169081611b585765ffffffffffff60a01b91505b5065ffffffffffff60a01b851680611b76575065ffffffffffff60a01b5b808218908211021880611b8f575065ffffffffffff60a01b5b92909217915b505092915050565b604080518082018252600681526512d95c9b995b60d21b602080830191909152825180840190935260058352640c0b8c8b8d60da1b9083015291565b600080516020612a218339815191525460501c6001600160a01b03811615611c135760405162dc149f60e41b815260040160405180910390fd5b600080516020612a218339815191528054600160501b600160f01b031916600160501b6001600160a01b0387169081029190911790915560405163064acaab60e11b8152630c959556906111a09086908690600401612615565b7ffbfed6646b979c9c720fcef5bc8de90666984c78fcce48057b7595d0ede6f6267f000000000000000000000000d3082872f8b06073a021b4602e022d5a070d7cfc30147f0000000000000000000000000000000000000000000000000000000000aa36a7461416611d605750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f32ba20807d2fff2dbb34e0bcfa82982565bef566d4c0c633dc57b700b81c342760208201527f9e7e907b5361ed55126e4f0e20b6f60c86b8b85222f1c3d6d1972657674943699181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b60005b83811015611da0578181015183820152602001611d88565b50506000910152565b60008151808452611dc1816020860160208601611d85565b601f01601f19169290920160200192915050565b6020815260006108d06020830184611da9565b6001600160a01b0381168114611dfd57600080fd5b50565b8035611e0b81611de8565b919050565b60008083601f840112611e2257600080fd5b5081356001600160401b03811115611e3957600080fd5b602083019150836020828501011115611e5157600080fd5b9250929050565b600080600080600060808688031215611e7057600080fd5b8535611e7b81611de8565b94506020860135611e8b81611de8565b93506040860135925060608601356001600160401b03811115611ead57600080fd5b611eb988828901611e10565b969995985093965092949392505050565b600080600060408486031215611edf57600080fd5b8335925060208401356001600160401b03811115611efc57600080fd5b611f0886828701611e10565b9497909650939450505050565b80356001600160e01b031981168114611e0b57600080fd5b65ffffffffffff81168114611dfd57600080fd5b600080600080600080600060c0888a031215611f5c57600080fd5b611f6588611f15565b96506020880135611f7581611de8565b95506040880135611f8581611de8565b94506060880135611f9581611f2d565b93506080880135611fa581611f2d565b925060a08801356001600160401b03811115611fc057600080fd5b611fcc8a828b01611e10565b989b979a50959850939692959293505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561201757612017611fdf565b60405290565b60405161016081016001600160401b038111828210171561201757612017611fdf565b604051601f8201601f191681016001600160401b038111828210171561206857612068611fdf565b604052919050565b600082601f83011261208157600080fd5b81356001600160401b0381111561209a5761209a611fdf565b6120ad601f8201601f1916602001612040565b8181528460208386010111156120c257600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156120f257600080fd5b82356001600160401b038082111561210957600080fd5b818501915085601f83011261211d57600080fd5b81358181111561212f5761212f611fdf565b8060051b61213e858201612040565b918252838101850191858101908984111561215857600080fd5b86860192505b8383101561163e578235858111156121765760008081fd5b86016060818c03601f190181131561218e5760008081fd5b612196611ff5565b898301356121a381611de8565b81526040838101358b8301529183013591888311156121c25760008081fd5b6121d08e8c85870101612070565b9082015284525050918601919086019061215e565b6000602082840312156121f757600080fd5b81356108d081611de8565b60008060006060848603121561221757600080fd5b83356001600160401b0381111561222d57600080fd5b8401610160818703121561224057600080fd5b95602085013595506040909401359392505050565b60006020828403121561226757600080fd5b81356001600160c01b03811681146108d057600080fd5b60006020828403121561229057600080fd5b6108d082611f15565b600080600080608085870312156122af57600080fd5b84356122ba81611de8565b93506020850135925060408501356001600160401b038111156122dc57600080fd5b6122e887828801612070565b9250506060850135600281106122fd57600080fd5b939692955090935050565b60008060006040848603121561231d57600080fd5b833561232881611de8565b925060208401356001600160401b03811115611efc57600080fd5b60ff60f81b881681526000602060e08184015261236360e084018a611da9565b8381036040850152612375818a611da9565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156123c7578351835292840192918401916001016123ab565b50909c9b505050505050505050505050565b600080604083850312156123ec57600080fd5b82356123f781611de8565b915060208301356001600160401b0381111561241257600080fd5b61241e85828601612070565b9150509250929050565b60008083601f84011261243a57600080fd5b5081356001600160401b0381111561245157600080fd5b6020830191508360208260051b8501011115611e5157600080fd5b60008060008060008060008060a0898b03121561248857600080fd5b883561249381611de8565b975060208901356124a381611de8565b965060408901356001600160401b03808211156124bf57600080fd5b6124cb8c838d01612428565b909850965060608b01359150808211156124e457600080fd5b6124f08c838d01612428565b909650945060808b013591508082111561250957600080fd5b506125168b828c01611e10565b999c989b5096995094979396929594505050565b60008060008060008060a0878903121561254357600080fd5b863561254e81611de8565b9550602087013561255e81611de8565b9450604087013593506060870135925060808701356001600160401b0381111561258757600080fd5b61259389828a01611e10565b979a9699509497509295939492505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038416815260406020820181905260009061144490830184866125a5565b60006020828403121561260557600080fd5b815180151581146108d057600080fd5b602081526000610ad16020830184866125a5565b634e487b7160e01b600052603260045260246000fd5b6000808585111561264f57600080fd5b8386111561265c57600080fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015611b955760049490940360031b84901b1690921692915050565b600061016082360312156126aa57600080fd5b6126b261201d565b6126bb83611e00565b81526020830135602082015260408301356001600160401b03808211156126e157600080fd5b6126ed36838701612070565b6040840152606085013591508082111561270657600080fd5b61271236838701612070565b60608401526080850135608084015260a085013560a084015260c085013560c084015260e085013560e0840152610100915081850135828401526101209150818501358181111561276257600080fd5b61276e36828801612070565b83850152506101409150818501358181111561278957600080fd5b61279536828801612070565b8385015250505080915050919050565b606081526127bf6060820185516001600160a01b03169052565b60208401516080820152600060408501516101608060a08501526127e76101c0850183611da9565b91506060870151605f19808685030160c08701526128058483611da9565b9350608089015160e087015260a08901519150610100828188015260c08a01519250610120838189015260e08b0151935061014084818a0152828c0151868a0152818c0151955083898803016101808a01526128618787611da9565b9650808c0151955050505080868503016101a087015250506128838282611da9565b602085019690965250505060400152919050565b6000602082840312156128a957600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b8381526040602082015260006114446040830184866125a5565b600084516128f2818460208901611d85565b919091019283525060601b6001600160601b0319166020820152603401919050565b60008251612926818460208701611d85565b9190910192915050565b6000808335601e1984360301811261294757600080fd5b8301803591506001600160401b0382111561296157600080fd5b602001915036819003821315611e5157600080fd5b6001600160601b03198135818116916014851015611b955760149490940360031b84901b1690921692915050565b80356020831015610ff657600019602084900360031b1b1692915050565b8183823760009101908152919050565b6001600160d01b03198135818116916006851015611b955760069490940360031b84901b169092169291505056fe439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd8439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd9

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789

-----Decoded View---------------
Arg [0] : _entryPoint (address): 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.