ETH Price: $1,960.99 (-1.61%)
Gas: 0.04 Gwei
 

Overview

Max Total Supply

0 Kernel

Holders

0

Transfers

-
0

Market

Onchain Market Cap

-

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 0 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
Kernel

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Importing external libraries and contracts
import "solady/utils/EIP712.sol";
import "solady/utils/ECDSA.sol";
import "account-abstraction/interfaces/IEntryPoint.sol";
import "./abstract/Compatibility.sol";
import "./abstract/KernelStorage.sol";
import "./utils/KernelHelper.sol";

import "src/common/Constants.sol";
import "src/common/Enum.sol";

/// @title Kernel
/// @author taek<leekt216@gmail.com>
/// @notice wallet kernel for extensible wallet functionality

contract Kernel is EIP712, Compatibility, KernelStorage {
    string public constant name = KERNEL_NAME;

    string public constant version = KERNEL_VERSION;

    error NotEntryPoint();
    error DisabledMode();

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

    function _domainNameAndVersion() internal pure override returns (string memory, string memory) {
        return (KERNEL_NAME, KERNEL_VERSION);
    }

    /// @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
    /// @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
    /// @param operation The type of operation (call or delegatecall)
    function execute(address to, uint256 value, bytes memory data, Operation operation) external payable {
        if (msg.sender != address(entryPoint) && !_checkCaller()) {
            revert NotAuthorizedCaller();
        }
        if (operation == Operation.Call) {
            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()) }
            }
        } else {
            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 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)
    {
        if (msg.sender != address(entryPoint)) {
            revert NotEntryPoint();
        }
        bytes calldata userOpSignature;
        uint256 userOpEndOffset;
        bytes32 storage_slot_1;
        assembly {
            userOpEndOffset := add(calldataload(0x04), 0x24)
            userOpSignature.offset := add(calldataload(add(userOpEndOffset, 0x120)), userOpEndOffset)
            userOpSignature.length := calldataload(sub(userOpSignature.offset, 0x20))
            storage_slot_1 := sload(KERNEL_STORAGE_SLOT_1)
        }
        // mode based signature
        bytes4 mode = bytes4(userOpSignature[0:4]); // mode == 00..00 use validators
        // mode == 0x00000000 use sudo validator
        // mode == 0x00000001 use given validator
        // mode == 0x00000002 enable validator
        IKernelValidator validator;
        if (mode == 0x00000000) {
            // sudo mode (use default validator)
            userOpSignature = userOpSignature[4:];
            assembly {
                validator := shr(80, storage_slot_1)
            }
        } else if (mode & (storage_slot_1 << 224) != 0x00000000) {
            revert DisabledMode();
        } else 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;
            if (address(validator) == address(0)) {
                assembly {
                    validator := shr(80, storage_slot_1)
                }
            }
            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;
        }
        if (missingAccountFunds != 0) {
            assembly {
                pop(call(gas(), caller(), missingAccountFunds, 0, 0, 0, 0))
            }
            //ignore failure (its EntryPoint's job to verify, not account.)
        }
        userOp.signature = userOpSignature;
        validationData =
            _intersectValidationData(validationData, validator.validateUserOp(userOp, userOpHash, missingAccountFunds));
        return validationData;
    }

    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(
                getKernelStorage().defaultValidator.validateSignature(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);
        }
    }

    /// @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) external view returns (bytes4) {
        ValidationData validationData = getKernelStorage().defaultValidator.validateSignature(hash, signature);
        (ValidAfter validAfter, ValidUntil validUntil, address result) = parseValidationData(validationData);
        if (ValidAfter.unwrap(validAfter) > block.timestamp) {
            return 0xffffffff;
        }
        if (ValidUntil.unwrap(validUntil) < block.timestamp) {
            return 0xffffffff;
        }
        if (result != address(0)) {
            return 0xffffffff;
        }

        return 0x1626ba7e;
    }

    function _checkCaller() internal view returns (bool) {
        if (getKernelStorage().defaultValidator.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);
        }
    }
}

// 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)
/// 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;

    address 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 = address(this);
        _cachedChainId = block.chainid;

        (string memory name, string memory version) = _domainNameAndVersion();
        bytes32 nameHash = keccak256(bytes(name));
        bytes32 versionHash = keccak256(bytes(version));
        _cachedNameHash = nameHash;
        _cachedVersionHash = versionHash;

        bytes32 separator;
        /// @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";
    ///     }
    /// ```
    function _domainNameAndVersion()
        internal
        pure
        virtual
        returns (string memory name, string memory version);

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

    /// @dev Returns the EIP-712 domain separator.
    function _domainSeparator() internal view virtual returns (bytes32 separator) {
        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) {
        bytes32 separator = _cachedDomainSeparator;
        if (_cachedDomainSeparatorInvalidated()) {
            separator = _buildDomainSeparator();
        }
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the digest.
            mstore(0x00, 0x1901000000000000) // Store "\x19\x01".
            mstore(0x1a, separator) // 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) {
        bytes32 nameHash = _cachedNameHash;
        bytes32 versionHash = _cachedVersionHash;
        /// @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)
        }
    }

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

// 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)
library ECDSA {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

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

    /// @dev The number which `s` must not exceed in order for
    /// the signature to be non-malleable.
    bytes32 private constant _MALLEABILITY_THRESHOLD =
        0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;

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

    // Note: as of Solady version 0.0.68, these functions will
    // revert upon recovery failure for more safety by default.

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            // Copy `r` and `s`.
            mstore(0x40, mload(add(signature, 0x20))) // `r`.
            let s := mload(add(signature, 0x40))
            mstore(0x60, s)
            // Store the `hash` in the scratch space.
            mstore(0x00, hash)
            // Compute `v` and store it in the scratch space.
            mstore(0x20, byte(0, mload(add(signature, 0x60))))
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    and(
                        // If the signature is exactly 65 bytes in length.
                        eq(mload(signature), 65),
                        // If `s` in lower half order, such that the signature is not malleable.
                        lt(s, add(_MALLEABILITY_THRESHOLD, 1))
                    ), // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x00, // Start of output.
                    0x20 // Size of output.
                )
            )
            result := mload(0x00)
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                // Store the function selector of `InvalidSignature()`.
                mstore(0x00, 0x8baa579f)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the zero slot.
            mstore(0x60, 0)
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function recoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            // Directly copy `r` and `s` from the calldata.
            calldatacopy(0x40, signature.offset, 0x40)
            // Store the `hash` in the scratch space.
            mstore(0x00, hash)
            // Compute `v` and store it in the scratch space.
            mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40))))
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    and(
                        // If the signature is exactly 65 bytes in length.
                        eq(signature.length, 65),
                        // If `s` in lower half order, such that the signature is not malleable.
                        lt(mload(0x60), add(_MALLEABILITY_THRESHOLD, 1))
                    ), // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x00, // Start of output.
                    0x20 // Size of output.
                )
            )
            result := mload(0x00)
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                // Store the function selector of `InvalidSignature()`.
                mstore(0x00, 0x8baa579f)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the zero slot.
            mstore(0x60, 0)
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    ///
    /// This function only accepts EIP-2098 short form signatures.
    /// See: https://eips.ethereum.org/EIPS/eip-2098
    ///
    /// To be honest, I do not recommend using EIP-2098 signatures
    /// for simplicity, performance, and security reasons. Most if not
    /// all clients support traditional non EIP-2098 signatures by default.
    /// As such, this method is intentionally not fully inlined.
    /// It is merely included for completeness.
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
        uint8 v;
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(1, shl(1, vs))
            v := add(shr(255, vs), 27)
        }
        result = recover(hash, v, r, s);
    }

    /// @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 {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            mstore(0x00, hash)
            mstore(0x20, and(v, 0xff))
            mstore(0x40, r)
            mstore(0x60, s)
            pop(
                staticcall(
                    gas(), // Amount of gas left for the transaction.
                    // If `s` in lower half order, such that the signature is not malleable.
                    lt(s, add(_MALLEABILITY_THRESHOLD, 1)), // Address of `ecrecover`.
                    0x00, // Start of input.
                    0x80, // Size of input.
                    0x00, // Start of output.
                    0x20 // Size of output.
                )
            )
            result := mload(0x00)
            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
            if iszero(returndatasize()) {
                // Store the function selector of `InvalidSignature()`.
                mstore(0x00, 0x8baa579f)
                // Revert with (offset, size).
                revert(0x1c, 0x04)
            }
            // Restore the zero slot.
            mstore(0x60, 0)
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   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`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function tryRecover(bytes32 hash, bytes memory signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(xor(mload(signature), 65)) {
                // Copy the free memory pointer so that we can restore it later.
                let m := mload(0x40)
                // Copy `r` and `s`.
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                let s := mload(add(signature, 0x40))
                mstore(0x60, s)
                // If `s` in lower half order, such that the signature is not malleable.
                if iszero(gt(s, _MALLEABILITY_THRESHOLD)) {
                    // Store the `hash` in the scratch space.
                    mstore(0x00, hash)
                    // Compute `v` and store it in the scratch space.
                    mstore(0x20, byte(0, mload(add(signature, 0x60))))
                    pop(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            0x01, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x40, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                    // Restore the zero slot.
                    mstore(0x60, 0)
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    result := mload(xor(0x60, returndatasize()))
                }
                // Restore the free memory pointer.
                mstore(0x40, m)
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the `signature`.
    ///
    /// This function does NOT accept EIP-2098 short form signatures.
    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
    /// short form signatures instead.
    function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
        internal
        view
        returns (address result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(xor(signature.length, 65)) {
                // Copy the free memory pointer so that we can restore it later.
                let m := mload(0x40)
                // Directly copy `r` and `s` from the calldata.
                calldatacopy(0x40, signature.offset, 0x40)
                // If `s` in lower half order, such that the signature is not malleable.
                if iszero(gt(mload(0x60), _MALLEABILITY_THRESHOLD)) {
                    // Store the `hash` in the scratch space.
                    mstore(0x00, hash)
                    // Compute `v` and store it in the scratch space.
                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40))))
                    pop(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            0x01, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x40, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                    // Restore the zero slot.
                    mstore(0x60, 0)
                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                    result := mload(xor(0x60, returndatasize()))
                }
                // Restore the free memory pointer.
                mstore(0x40, m)
            }
        }
    }

    /// @dev Recovers the signer's address from a message digest `hash`,
    /// and the EIP-2098 short form signature defined by `r` and `vs`.
    ///
    /// This function only accepts EIP-2098 short form signatures.
    /// See: https://eips.ethereum.org/EIPS/eip-2098
    ///
    /// To be honest, I do not recommend using EIP-2098 signatures
    /// for simplicity, performance, and security reasons. Most if not
    /// all clients support traditional non EIP-2098 signatures by default.
    /// As such, this method is intentionally not fully inlined.
    /// It is merely included for completeness.
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
        internal
        view
        returns (address result)
    {
        uint8 v;
        bytes32 s;
        /// @solidity memory-safe-assembly
        assembly {
            s := shr(1, shl(1, vs))
            v := add(shr(255, vs), 27)
        }
        result = tryRecover(hash, v, r, s);
    }

    /// @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 {
            // Copy the free memory pointer so that we can restore it later.
            let m := mload(0x40)
            // If `s` in lower half order, such that the signature is not malleable.
            if iszero(gt(s, _MALLEABILITY_THRESHOLD)) {
                // Store the `hash`, `v`, `r`, `s` in the scratch space.
                mstore(0x00, hash)
                mstore(0x20, and(v, 0xff))
                mstore(0x40, r)
                mstore(0x60, s)
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        0x01, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                // Restore the zero slot.
                mstore(0x60, 0)
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
            }
            // Restore the free memory pointer.
            mstore(0x40, m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     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 {
            // Store into scratch space for keccak256.
            mstore(0x20, hash)
            mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32")
            // 0x40 - 0x04 = 0x3c
            result := keccak256(0x04, 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.
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
        assembly {
            // The length of "\x19Ethereum Signed Message:\n" is 26 bytes (i.e. 0x1a).
            // If we reserve 2 words, we'll have 64 - 26 = 38 bytes to store the
            // ASCII decimal representation of the length of `s` up to about 2 ** 126.

            // Instead of allocating, we temporarily copy the 64 bytes before the
            // start of `s` data to some variables.
            let m := mload(sub(s, 0x20))
            // The length of `s` is in bytes.
            let sLength := mload(s)
            let ptr := add(s, 0x20)
            let w := not(0)
            // `end` marks the end of the memory which we will compute the keccak256 of.
            let end := add(ptr, sLength)
            // Convert the length of the bytes to ASCII decimal representation
            // and store it into the memory.
            for { let temp := sLength } 1 {} {
                ptr := add(ptr, w) // `sub(ptr, 1)`.
                mstore8(ptr, add(48, mod(temp, 10)))
                temp := div(temp, 10)
                if iszero(temp) { break }
            }
            // Copy the header over to the memory.
            mstore(sub(ptr, 0x20), "\x00\x00\x00\x00\x00\x00\x19Ethereum Signed Message:\n")
            // Compute the keccak256 of the memory.
            result := keccak256(sub(ptr, 0x1a), sub(end, sub(ptr, 0x1a)))
            // Restore the previous memory.
            mstore(s, sLength)
            mstore(sub(s, 0x20), m)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   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
        }
    }
}

/**
 ** 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.
     */
    event SignatureAggregatorChanged(address indexed aggregator);

    /**
     * a custom revert error of handleOps, to identify the offending op.
     *  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.
     *   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.
     */
    error FailedOp(uint256 opIndex, string reason);

    /**
     * error case when a signature aggregator fails to verify the aggregated signature it had created.
     */
    error SignatureValidationFailed(address aggregator);

    /**
     * Successful result from simulateValidation.
     * @param returnInfo gas and time-range returned values
     * @param senderInfo stake information about the sender
     * @param factoryInfo stake information about the factory (if any)
     * @param paymasterInfo stake information about the paymaster (if any)
     */
    error ValidationResult(ReturnInfo returnInfo,
        StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);

    /**
     * Successful result from simulateValidation, if the account returns a signature aggregator
     * @param returnInfo gas and time-range returned values
     * @param senderInfo stake information about the sender
     * @param factoryInfo stake information about the factory (if any)
     * @param paymasterInfo stake information about the paymaster (if any)
     * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)
     *      bundler MUST use it to verify the signature, or reject the UserOperation
     */
    error ValidationResultWithAggregation(ReturnInfo returnInfo,
        StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,
        AggregatorStakeInfo aggregatorInfo);

    /**
     * return value of getSenderAddress
     */
    error SenderAddressResult(address sender);

    /**
     * return value of simulateHandleOp
     */
    error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);

    //UserOps handled, per aggregator
    struct UserOpsPerAggregator {
        UserOperation[] userOps;

        // aggregator address
        IAggregator aggregator;
        // aggregated signature
        bytes signature;
    }

    /**
     * Execute a batch of UserOperation.
     * 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.
     */
    function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);

    /**
     * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.
     * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.
     * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.
     * @param userOp the user operation to validate.
     */
    function simulateValidation(UserOperation calldata userOp) external;

    /**
     * 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;


    /**
     * simulate full execution of a UserOperation (including both validation and target execution)
     * this method will always revert with "ExecutionResult".
     * it performs full validation of the UserOperation, but ignores signature error.
     * an optional target address is called after the userop succeeds, and its value is returned
     * (before the entire call is reverted)
     * Note that in order to collect the the success/failure of the target call, it must be executed
     * with trace enabled to track the emitted events.
     * @param op the UserOperation to simulate
     * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult
     *        are set to the return from that call.
     * @param targetCallData callData to pass to target address
     */
    function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;
}

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

abstract contract Compatibility {
    receive() external payable {}

    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;
    }
}

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

// Importing necessary interfaces
import "account-abstraction/interfaces/IEntryPoint.sol";
import "src/interfaces/IValidator.sol";
import "src/common/Constants.sol";
import "src/common/Structs.sol";

/// @title Kernel Storage Contract
/// @author taek<leekt216@gmail.com>
/// @notice This contract serves as the storage module for the Kernel contract.
/// @dev This contract should only be used by the main Kernel contract.
contract KernelStorage {
    IEntryPoint public immutable entryPoint; // The entry point of the contract

    // 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();

    // 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 {
        _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 onlyFromEntryPointOrSelf {
        assembly {
            sstore(IMPLEMENTATION_SLOT, _newImplementation)
        }
        emit Upgraded(_newImplementation);
    }

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

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

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

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

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

    /// @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) public view returns (ExecutionDetail memory) {
        return getKernelStorage().execution[_selector];
    }

    /// @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,
        uint48 _validUntil,
        uint48 _validAfter,
        bytes calldata _enableData
    ) external payable onlyFromEntryPointOrSelf {
        getKernelStorage().execution[_selector] = ExecutionDetail({
            executor: _executor,
            validator: _validator,
            validUntil: ValidUntil.wrap(_validUntil),
            validAfter: ValidAfter.wrap(_validAfter)
        });
        _validator.enable(_enableData);
        emit ExecutionChanged(_selector, _executor, address(_validator));
    }

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

    /// @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 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 7 of 17 : KernelHelper.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {SIG_VALIDATION_FAILED_UINT} from "src/common/Constants.sol";
import {ValidationData} from "src/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
        switch iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff))
        case 1 {
            // validAfter
            let a_vd := and(0xffffffffffff000000000000ffffffffffffffffffffffffffffffffffffffff, a)
            let b_vd := and(0xffffffffffff000000000000ffffffffffffffffffffffffffffffffffffffff, b)
            validationData := xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd)))
            // validUntil
            a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a)
            b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b)
            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 8 of 17 : Constants.sol
pragma solidity ^0.8.0;

// constants for kernel metadata
string constant KERNEL_NAME = "Kernel";
string constant KERNEL_VERSION = "0.2.1";

// ERC4337 constants
uint256 constant SIG_VALIDATION_FAILED_UINT = 1;

// STRUCT_HASH
bytes32 constant VALIDATOR_APPROVED_STRUCT_HASH = 0x3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee964176;

// Storage slots
bytes32 constant KERNEL_STORAGE_SLOT = 0x439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd8;
bytes32 constant KERNEL_STORAGE_SLOT_1 = 0x439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd9;
bytes32 constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

File 9 of 17 : Enum.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
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;

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

import {calldataKeccak} from "../core/Helpers.sol";

/**
 * 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;
    }

/**
 * Utility functions helpful when working with UserOperation structs.
 */
library UserOperationLib {

    function getSender(UserOperation calldata userOp) internal pure returns (address) {
        address data;
        //read sender from userOp, which is first userOp member (saves 800 gas...)
        assembly {data := calldataload(userOp)}
        return address(uint160(data));
    }

    //relayer/block builder might submit the TX with higher priorityFee, but the user should not
    // pay above what he signed for.
    function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {
    unchecked {
        uint256 maxFeePerGas = userOp.maxFeePerGas;
        uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;
        if (maxFeePerGas == maxPriorityFeePerGas) {
            //legacy mode (for networks that don't support basefee opcode)
            return maxFeePerGas;
        }
        return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
    }
    }

    function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {
        address sender = getSender(userOp);
        uint256 nonce = userOp.nonce;
        bytes32 hashInitCode = calldataKeccak(userOp.initCode);
        bytes32 hashCallData = calldataKeccak(userOp.callData);
        uint256 callGasLimit = userOp.callGasLimit;
        uint256 verificationGasLimit = userOp.verificationGasLimit;
        uint256 preVerificationGas = userOp.preVerificationGas;
        uint256 maxFeePerGas = userOp.maxFeePerGas;
        uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;
        bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);

        return abi.encode(
            sender, nonce,
            hashInitCode, hashCallData,
            callGasLimit, verificationGasLimit, preVerificationGas,
            maxFeePerGas, maxPriorityFeePerGas,
            hashPaymasterAndData
        );
    }

    function hash(UserOperation calldata userOp) internal pure returns (bytes32) {
        return keccak256(pack(userOp));
    }

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

// 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;
    }

    /// @return info - full deposit information of given account
    function getDepositInfo(address account) external view returns (DepositInfo memory info);

    /// @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
     */
    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;
}

// 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.
     */
    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);
}

// 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;
}

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

import {UserOperation} from "account-abstraction/interfaces/UserOperation.sol";
import "src/common/Types.sol";

interface IKernelValidator {
    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 15 of 17 : Structs.sol
pragma solidity ^0.8.0;

import "src/interfaces/IValidator.sol";
import "src/common/Enum.sol";
import "src/common/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
}

// 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 ParamRule {
    uint256 offset;
    ParamCondition condition;
    bytes32 param;
}

struct Permission {
    address target;
    uint256 valueLimit;
    bytes4 sig;
    ParamRule[] rules;
    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
    bool enabled;
}

pragma solidity ^0.8.9;

import "src/common/Constants.sol";

type ValidAfter is uint48;

type ValidUntil is uint48;

type ValidationData is uint256;

ValidationData constant SIG_VALIDATION_FAILED = ValidationData.wrap(SIG_VALIDATION_FAILED_UINT);

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

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)
    }
}

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;

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

/**
 * returned data from validateUserOp.
 * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`
 * @param aggregator - address(0) - the account validated the signature by itself.
 *              address(1) - the account failed to validate the signature.
 *              otherwise - this is an address of a signature aggregator that must be used to validate the signature.
 * @param validAfter - this UserOp is valid only after this timestamp.
 * @param validaUntil - this UserOp is valid only up to this timestamp.
 */
    struct ValidationData {
        address aggregator;
        uint48 validAfter;
        uint48 validUntil;
    }

//extract sigFailed, validAfter, validUntil.
// also convert zero validUntil to type(uint48).max
    function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {
        address aggregator = address(uint160(validationData));
        uint48 validUntil = uint48(validationData >> 160);
        if (validUntil == 0) {
            validUntil = type(uint48).max;
        }
        uint48 validAfter = uint48(validationData >> (48 + 160));
        return ValidationData(aggregator, validAfter, validUntil);
    }

// intersect account and paymaster ranges.
    function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {
        ValidationData memory accountValidationData = _parseValidationData(validationData);
        ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);
        address aggregator = accountValidationData.aggregator;
        if (aggregator == address(0)) {
            aggregator = pmValidationData.aggregator;
        }
        uint48 validAfter = accountValidationData.validAfter;
        uint48 validUntil = accountValidationData.validUntil;
        uint48 pmValidAfter = pmValidationData.validAfter;
        uint48 pmValidUntil = pmValidationData.validUntil;

        if (validAfter < pmValidAfter) validAfter = pmValidAfter;
        if (validUntil > pmValidUntil) validUntil = pmValidUntil;
        return ValidationData(aggregator, validAfter, validUntil);
    }

/**
 * helper to pack the return value for validateUserOp
 * @param data - the ValidationData to pack
 */
    function _packValidationData(ValidationData memory data) pure returns (uint256) {
        return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));
    }

/**
 * helper to pack the return value for validateUserOp, when not using an aggregator
 * @param sigFailed - true for signature failure, false for success
 * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)
 * @param validAfter first timestamp this UserOperation is valid
 */
    function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {
        return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));
    }

/**
 * keccak function over calldata.
 * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.
 */
    function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
        assembly {
            let mem := mload(0x40)
            let len := data.length
            calldatacopy(mem, data.offset, len)
            ret := keccak256(mem, len)
        }
    }

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IEntryPoint","name":"_entryPoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","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":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":[],"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":"uint48","name":"_validUntil","type":"uint48"},{"internalType":"uint48","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":[{"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"}]

61014034620001b057601f62001f9f38819003918201601f19168301916001600160401b03831184841017620001b557808492602094604052833981010312620001b057516001600160a01b0381168103620001b057306080524660a05260a062000069620001cb565b600681526005602082016512d95c9b995b60d21b815260206200008b620001cb565b838152019264302e322e3160d81b845251902091208160c0528060e052604051917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83526020830152604082015246606082015230608082015220906101009182526101209081527f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd96a010000000000000000000080600160f01b031982541617905560405190611db39283620001ec8439608051836118fc015260a0518361191f015260c05183611991015260e051836119b7015251826118db01525181818161049d01528181610654015281816108ad01528181610a3801528181610b5f01528181610d5901528181610e7a01528181610f7b015281816110a501526112f50152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b60408051919082016001600160401b03811183821017620001b55760405256fe60806040526004361015610015575b3661108857005b60003560e01c806306fdde03146101655780630b3dc35414610160578063150b7a021461015b5780631626ba7e1461015657806329f8b174146101515780633659cfe61461014c5780633a871cdd146101475780633e1b08121461014257806351166ba01461013d578063519454471461013857806354fd4d501461013357806355b14f501461012e57806357b750471461012957806384b0196e1461012457806388e7fd061461011f578063b0d691fe1461011a578063bc197c8114610115578063d087d28814610110578063d1f578941461010b578063d5416221146101065763f23a6e610361000e57610ff6565b610f64565b610ec6565b610e47565b610db8565b610d43565b610d0e565b610c66565b610c2f565b610b49565b610af1565b6109f1565b610928565b610864565b61073a565b610630565b61042f565b61039d565b610343565b6102c4565b610290565b600091031261017557565b600080fd5b634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116101a357604052565b61017a565b608081019081106001600160401b038211176101a357604052565b604081019081106001600160401b038211176101a357604052565b90601f801991011681019081106001600160401b038211176101a357604052565b6040519061020c826101a8565b565b6040519061016082018281106001600160401b038211176101a357604052565b6040519061023b826101c3565b600682526512d95c9b995b60d21b6020830152565b919082519283825260005b84811061027c575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161025b565b34610175576000366003190112610175576102c06102ac61022e565b604051918291602083526020830190610250565b0390f35b34610175576000366003190112610175576020600080516020611d938339815191525460501c6040519060018060a01b03168152f35b6001600160a01b0381160361017557565b359061020c826102fa565b9181601f84011215610175578235916001600160401b038311610175576020838186019501011161017557565b346101755760803660031901126101755761035f6004356102fa565b61036a6024356102fa565b6064356001600160401b03811161017557610389903690600401610316565b5050604051630a85bd0160e11b8152602090f35b34610175576040366003190112610175576024356001600160401b038111610175576103db6103d26020923690600401610316565b906004356119ed565b6040516001600160e01b03199091168152f35b600435906001600160e01b03198216820361017557565b6064359065ffffffffffff8216820361017557565b6084359065ffffffffffff8216820361017557565b60c0366003190112610175576104436103ee565b60243590610450826102fa565b6044359061045d826102fa565b610465610405565b9261046e61041a565b9060a4356001600160401b0381116101755761048e903690600401610316565b9590946001600160a01b0393337f00000000000000000000000000000000000000000000000000000000000000008616141580610626575b6106145784926104f0610587926104db6101ff565b65ffffffffffff918216815292166020830152565b6001600160a01b03851660408201526001600160a01b038316606082015261051787611050565b81516020830151604084015160309190911b6bffffffffffff0000000000001665ffffffffffff9290921691909117606091821b6bffffffffffffffffffffffff19161782559091015160019190910180546001600160a01b0319166001600160a01b0392909216919091179055565b1693843b15610175576040519063064acaab60e11b825281806105b16000998a94600484016115ed565b038183895af1801561060f576105f6575b5016906001600160e01b0319167fed03d2572564284398470d3f266a693e29ddfff3eba45fc06c5e91013d3213538480a480f35b8061060361060992610190565b8061016a565b386105c2565b6112d5565b604051637046c88d60e01b8152600490fd5b50303314156104c6565b602036600319011261017557600435610648816102fa565b6001600160a01b0390337f000000000000000000000000000000000000000000000000000000000000000083161415806106cc575b61061457807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a2005b503033141561067d565b9291926001600160401b0382116101a357604051916106ff601f8201601f1916602001846101de565b829481845281830111610175578281602093846000960137010152565b9080601f8301121561017557816020610737933591016106d6565b90565b6003196060368201126101755760048035916001600160401b0390818411610175576101609084360301126101755761077161020e565b9061077d84840161030b565b8252602484013560208301526044840135818111610175576107a49084369187010161071c565b60408301526064840135818111610175576107c49084369187010161071c565b60608301526084840135608083015260a484013560a083015260c484013560c083015260e484013560e0830152610104840135610100830152610124840135818111610175576108199084369187010161071c565b610120830152610144840135908111610175576102c09361085493610841923692010161071c565b61014082015260443590602435906112e1565b6040519081529081906020820190565b34610175576020366003190112610175576004356001600160c01b0381169081900361017557604051631aab3f0d60e11b815230600482015260248101919091526020816044817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa801561060f576102c0916000916108fa575b506040519081529081906020820190565b61091b915060203d8111610921575b61091381836101de565b8101906111f6565b386108e9565b503d610909565b34610175576020366003190112610175576102c061096d6109476103ee565b60006060604051610957816101a8565b8281528260208201528260408201520152611050565b6040519061097a826101a8565b805465ffffffffffff80821684528160301c16602084015260601c60408301526001808060a01b03910154166060820152604051918291829190916060608082019365ffffffffffff80825116845260208201511660208401528160018060a01b0391826040820151166040860152015116910152565b608036600319011261017557600435610a09816102fa565b6044356001600160401b03811161017557610a2890369060040161071c565b90606435600281101561017557337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316141580610abb575b61061457610a7581611101565b610a9e576000828193926020839451920190602435905af13d82803e15610a9a573d90f35b3d90fd5b60008281939260208394519201905af43d82803e15610a9a573d90f35b50610acb610ac7611b20565b1590565b610a68565b60405190610add826101c3565b6005825264302e322e3160d81b6020830152565b34610175576000366003190112610175576102c06102ac610ad0565b90604060031983011261017557600435610b26816102fa565b91602435906001600160401b03821161017557610b4591600401610316565b9091565b610b5236610b0d565b90916001600160a01b03337f00000000000000000000000000000000000000000000000000000000000000008216141580610c25575b6106145780600080516020611d938339815191525460501c1691610bab81611cb6565b1692836040519360009586947fa35f5cdc5fbabb614b4cd5064ce5543f43dc8fab0e4da41255230eb8aba2531c8680a3813b15610c21578385610bff819593829463064acaab60e11b8452600484016115ed565b03925af1801561060f57610c11575080f35b80610603610c1e92610190565b80f35b8380fd5b5030331415610b88565b34610175576000366003190112610175576020600080516020611d938339815191525460e01b6040519063ffffffff60e01b168152f35b3461017557600036600319011261017557610cbc610c8261022e565b610c8a610ad0565b90604051928392600f60f81b8452610cae60209360e08587015260e0860190610250565b908482036040860152610250565b90466060840152306080840152600060a084015282820360c08401528060605192838152019160809160005b828110610cf757505050500390f35b835185528695509381019392810192600101610ce8565b34610175576000366003190112610175576020600080516020611d938339815191525465ffffffffffff60405191831c168152f35b34610175576000366003190112610175576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b9181601f84011215610175578235916001600160401b038311610175576020808501948460051b01011161017557565b346101755760a036600319011261017557610dd46004356102fa565b610ddf6024356102fa565b6001600160401b0360443581811161017557610dff903690600401610d88565b505060643581811161017557610e19903690600401610d88565b505060843590811161017557610e33903690600401610316565b505060405163bc197c8160e01b8152602090f35b3461017557600036600319011261017557604051631aab3f0d60e11b8152306004820152600060248201526020816044817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa801561060f576102c0916000916108fa57506040519081529081906020820190565b610ecf36610b0d565b600080516020611d9383398151915254919290916001600160a01b03919060501c8216610f5357610eff81611cb6565b1691823b1561017557610f34926000928360405180968195829463064acaab60e11b8452602060048501526024840191611589565b03925af1801561060f57610f4457005b80610603610f5192610190565b005b60405162dc149f60e41b8152600490fd5b602036600319011261017557610f786103ee565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316141580610fec575b61061457600080516020611d9383398151915290815469ffffffffffff000000004260201b169160e01c9069ffffffffffffffffffff191617179055600080f35b5030331415610fab565b346101755760a0366003190112610175576110126004356102fa565b61101d6024356102fa565b6084356001600160401b0381116101755761103c903690600401610316565b505060405163f23a6e6160e01b8152602090f35b63ffffffff60e01b166000527f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda602052604060002090565b600061109e81356001600160e01b031916611050565b5460601c337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161415806110f2575b61061457818091368280378136915af43d82803e15610a9a573d90f35b506110fb611b20565b156110d5565b6002111561110b57565b634e487b7160e01b600052602160045260246000fd5b906004116101755790600490565b909291928360041161017557831161017557600401916003190190565b906024116101755760100190601490565b906058116101755760380190602090565b906024116101755760040190602090565b906038116101755760240190601490565b90600a116101755760040190600690565b9060101161017557600a0190600690565b90939293848311610175578411610175578101920390565b6001600160e01b031990358181169392600481106111e757505050565b60040360031b82901b16169150565b90816020910312610175575190565b606080825282516001600160a01b031690820152919392916040916112cb90602081015160808401528381015161124a610160918260a08701526101c0860190610250565b906112b861126a606085015193605f1994858983030160c08a0152610250565b608085015160e088015260a085015192610100938489015260c08601519061012091828a015260e08701519461014095868b0152870151908901528501518488830301610180890152610250565b92015190848303016101a0850152610250565b9460208201520152565b6040513d6000823e3d90fd5b6001600160a01b03939260009290918391907f000000000000000000000000000000000000000000000000000000000000000087163303611529576004908135978861014481013501928060248501940135600080516020611d9383398151915254946113576113518383611121565b906111ca565b9b6001600160e01b0319808e16908161140c57505050899a9b50611386826020999a9b95949361139d9361112f565b9660501c965b858c806113fd575b505036916106d6565b6101408501526113c1604051998a9788968794633a871cdd60e01b86528501611205565b0393165af191821561060f5761073793926113dd575b50611d2c565b6113f691925060203d81116109215761091381836101de565b90386113d7565b81808092335af150858c611394565b9199509197969594939c8660e01b161615156000146114365760405163fc2f51c560e01b81528c90fd5b90899a9b91600160e09b95969798999a9b1b81146000146114d557506114776114726113518b606460209c9d0135016024868201359101611121565b611050565b60018101549099906001600160a01b031696848816156114ca575b508161139d926114a19261112f565b995460d081901b6001600160d01b03191660709190911b65ffffffffffff60a01b16179961138c565b60501c965081611492565b9198979095509250600160e11b0361151b5761151161139d948a9361150c6113518a606460209c01350160248d8201359101611121565b6115fe565b919992969161138c565b505050505050505050600190565b604051636b31ba1560e11b8152600490fd5b6bffffffffffffffffffffffff19903581811693926014811061155d57505050565b60140360031b82901b16169150565b35906020811061157a575090565b6000199060200360031b1b1690565b908060209392818452848401376000828201840152601f01601f1916010190565b604090610737949281528160208201520191611589565b6001600160d01b031990358181169392600681106115de57505050565b60060360031b82901b16169150565b916020610737938181520191611589565b9061162a61161e611618611612868561114c565b9061153b565b60601c90565b6001600160a01b031690565b9361163e611638858461115d565b9061156c565b60588301607882019461165961163887856058018a896111b2565b9661176261166a611638838961116e565b61167a611618611612858b61117f565b996117086116893689896106d6565b8051602091820120604080517f3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee9641768185019081526001600160e01b03198b169282019290925260608101969096526001600160a01b039e909e16608086015260a08086019190915284529b8c9361170060c0826101de565b5190206118d9565b600080516020611d9383398151915254909190611744906117349060501c6001600160a01b031661161e565b9189019b60788d0190878d6111b2565b60405163199ed7c960e11b81529586948593849391600485016115aa565b03915afa92831561060f576114726117a861186895610517946000916118bc575b506117a1611791878d61116e565b6001600160a01b0319929161156c565b1690611d2c565b9a898b016078019a85036077190199611858906118486117e86117dd6117d76117d18b86611190565b906115c1565b60d01c90565b65ffffffffffff1690565b9761181f61161e6116186116126118086117dd6117d76117d1888b6111a1565b94611819611618611612838b61117f565b9761114c565b9461183961182b6101ff565b65ffffffffffff909b168b52565b89019065ffffffffffff169052565b6001600160a01b03166040870152565b6001600160a01b03166060850152565b6001600160a01b03871691823b156101755761189e926000928360405180968195829463064acaab60e11b8452600484016115ed565b03925af1801561060f576118af5750565b8061060361020c92610190565b6118d391508d803d106109215761091381836101de565b38611783565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000030147f000000000000000000000000000000000000000000000000000000000000000046141615611966575b671901000000000000600052601a52603a526042601820906000603a52565b5060a06040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f0000000000000000000000000000000000000000000000000000000000000000604082015246606082015230608082015220611947565b600080516020611d9383398151915254611a3a93602093909291611a1c9060501c6001600160a01b031661161e565b916040519586948593849363199ed7c960e11b8552600485016115aa565b03915afa801561060f57611a5691600091611ab1575b50611d03565b9165ffffffffffff908142911611611aa15742911610611a94576001600160a01b0316611a8857630b135d3f60e11b90565b6001600160e01b031990565b506001600160e01b031990565b506001600160e01b031992915050565b611ac9915060203d81116109215761091381836101de565b38611a50565b90816020910312610175575180151581036101755790565b6001600160a01b0390911681526040602082018190528101829052606091806000848401376000828201840152601f01601f1916010190565b600080516020611d9383398151915254611b459060501c6001600160a01b031661161e565b6040519081639ea9bd5960e01b9182825260209384918180611b6b363360048401611ae7565b03915afa90811561060f57600091611c99575b50611c9257611b986000356001600160e01b031916611050565b6001810154909190611bb2906001600160a01b031661161e565b916001600160a01b03831615908115611c56575b8115611c32575b5015611bdb57505050600090565b829060405192839182528180611bf5363360048401611ae7565b03915afa91821561060f57600092611c0c57505090565b6107379250803d10611c2b575b611c2381836101de565b810190611acf565b503d611c19565b54611c45915065ffffffffffff166117dd565b65ffffffffffff4291161138611bcd565b905065ffffffffffff611c766117dd835465ffffffffffff9060301c1690565b168015159081611c88575b5090611bc6565b9050421138611c81565b5050600190565b611cb09150833d8511611c2b57611c2381836101de565b38611b7e565b600080516020611d9383398151915280547fffff0000000000000000000000000000000000000000ffffffffffffffffffff1660509290921b600160501b600160f01b0316919091179055565b8065ffffffffffff91828160a01c16928315600114611d24575b5060d01c92565b925038611d1d565b8082186001600160a01b031615600114611d47575050600190565b65ffffffffffff60a01b828116828216818118918111919091028082189465ffffffffffff60a01b199485169416929114611d8a575b5081811190821802181790565b925038611d7d56fe439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd90000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789

Deployed Bytecode

0x60806040526004361015610015575b3661108857005b60003560e01c806306fdde03146101655780630b3dc35414610160578063150b7a021461015b5780631626ba7e1461015657806329f8b174146101515780633659cfe61461014c5780633a871cdd146101475780633e1b08121461014257806351166ba01461013d578063519454471461013857806354fd4d501461013357806355b14f501461012e57806357b750471461012957806384b0196e1461012457806388e7fd061461011f578063b0d691fe1461011a578063bc197c8114610115578063d087d28814610110578063d1f578941461010b578063d5416221146101065763f23a6e610361000e57610ff6565b610f64565b610ec6565b610e47565b610db8565b610d43565b610d0e565b610c66565b610c2f565b610b49565b610af1565b6109f1565b610928565b610864565b61073a565b610630565b61042f565b61039d565b610343565b6102c4565b610290565b600091031261017557565b600080fd5b634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116101a357604052565b61017a565b608081019081106001600160401b038211176101a357604052565b604081019081106001600160401b038211176101a357604052565b90601f801991011681019081106001600160401b038211176101a357604052565b6040519061020c826101a8565b565b6040519061016082018281106001600160401b038211176101a357604052565b6040519061023b826101c3565b600682526512d95c9b995b60d21b6020830152565b919082519283825260005b84811061027c575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161025b565b34610175576000366003190112610175576102c06102ac61022e565b604051918291602083526020830190610250565b0390f35b34610175576000366003190112610175576020600080516020611d938339815191525460501c6040519060018060a01b03168152f35b6001600160a01b0381160361017557565b359061020c826102fa565b9181601f84011215610175578235916001600160401b038311610175576020838186019501011161017557565b346101755760803660031901126101755761035f6004356102fa565b61036a6024356102fa565b6064356001600160401b03811161017557610389903690600401610316565b5050604051630a85bd0160e11b8152602090f35b34610175576040366003190112610175576024356001600160401b038111610175576103db6103d26020923690600401610316565b906004356119ed565b6040516001600160e01b03199091168152f35b600435906001600160e01b03198216820361017557565b6064359065ffffffffffff8216820361017557565b6084359065ffffffffffff8216820361017557565b60c0366003190112610175576104436103ee565b60243590610450826102fa565b6044359061045d826102fa565b610465610405565b9261046e61041a565b9060a4356001600160401b0381116101755761048e903690600401610316565b9590946001600160a01b0393337f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27898616141580610626575b6106145784926104f0610587926104db6101ff565b65ffffffffffff918216815292166020830152565b6001600160a01b03851660408201526001600160a01b038316606082015261051787611050565b81516020830151604084015160309190911b6bffffffffffff0000000000001665ffffffffffff9290921691909117606091821b6bffffffffffffffffffffffff19161782559091015160019190910180546001600160a01b0319166001600160a01b0392909216919091179055565b1693843b15610175576040519063064acaab60e11b825281806105b16000998a94600484016115ed565b038183895af1801561060f576105f6575b5016906001600160e01b0319167fed03d2572564284398470d3f266a693e29ddfff3eba45fc06c5e91013d3213538480a480f35b8061060361060992610190565b8061016a565b386105c2565b6112d5565b604051637046c88d60e01b8152600490fd5b50303314156104c6565b602036600319011261017557600435610648816102fa565b6001600160a01b0390337f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278983161415806106cc575b61061457807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b600080a2005b503033141561067d565b9291926001600160401b0382116101a357604051916106ff601f8201601f1916602001846101de565b829481845281830111610175578281602093846000960137010152565b9080601f8301121561017557816020610737933591016106d6565b90565b6003196060368201126101755760048035916001600160401b0390818411610175576101609084360301126101755761077161020e565b9061077d84840161030b565b8252602484013560208301526044840135818111610175576107a49084369187010161071c565b60408301526064840135818111610175576107c49084369187010161071c565b60608301526084840135608083015260a484013560a083015260c484013560c083015260e484013560e0830152610104840135610100830152610124840135818111610175576108199084369187010161071c565b610120830152610144840135908111610175576102c09361085493610841923692010161071c565b61014082015260443590602435906112e1565b6040519081529081906020820190565b34610175576020366003190112610175576004356001600160c01b0381169081900361017557604051631aab3f0d60e11b815230600482015260248101919091526020816044817f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b03165afa801561060f576102c0916000916108fa575b506040519081529081906020820190565b61091b915060203d8111610921575b61091381836101de565b8101906111f6565b386108e9565b503d610909565b34610175576020366003190112610175576102c061096d6109476103ee565b60006060604051610957816101a8565b8281528260208201528260408201520152611050565b6040519061097a826101a8565b805465ffffffffffff80821684528160301c16602084015260601c60408301526001808060a01b03910154166060820152604051918291829190916060608082019365ffffffffffff80825116845260208201511660208401528160018060a01b0391826040820151166040860152015116910152565b608036600319011261017557600435610a09816102fa565b6044356001600160401b03811161017557610a2890369060040161071c565b90606435600281101561017557337f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b0316141580610abb575b61061457610a7581611101565b610a9e576000828193926020839451920190602435905af13d82803e15610a9a573d90f35b3d90fd5b60008281939260208394519201905af43d82803e15610a9a573d90f35b50610acb610ac7611b20565b1590565b610a68565b60405190610add826101c3565b6005825264302e322e3160d81b6020830152565b34610175576000366003190112610175576102c06102ac610ad0565b90604060031983011261017557600435610b26816102fa565b91602435906001600160401b03821161017557610b4591600401610316565b9091565b610b5236610b0d565b90916001600160a01b03337f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27898216141580610c25575b6106145780600080516020611d938339815191525460501c1691610bab81611cb6565b1692836040519360009586947fa35f5cdc5fbabb614b4cd5064ce5543f43dc8fab0e4da41255230eb8aba2531c8680a3813b15610c21578385610bff819593829463064acaab60e11b8452600484016115ed565b03925af1801561060f57610c11575080f35b80610603610c1e92610190565b80f35b8380fd5b5030331415610b88565b34610175576000366003190112610175576020600080516020611d938339815191525460e01b6040519063ffffffff60e01b168152f35b3461017557600036600319011261017557610cbc610c8261022e565b610c8a610ad0565b90604051928392600f60f81b8452610cae60209360e08587015260e0860190610250565b908482036040860152610250565b90466060840152306080840152600060a084015282820360c08401528060605192838152019160809160005b828110610cf757505050500390f35b835185528695509381019392810192600101610ce8565b34610175576000366003190112610175576020600080516020611d938339815191525465ffffffffffff60405191831c168152f35b34610175576000366003190112610175576040517f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b03168152602090f35b9181601f84011215610175578235916001600160401b038311610175576020808501948460051b01011161017557565b346101755760a036600319011261017557610dd46004356102fa565b610ddf6024356102fa565b6001600160401b0360443581811161017557610dff903690600401610d88565b505060643581811161017557610e19903690600401610d88565b505060843590811161017557610e33903690600401610316565b505060405163bc197c8160e01b8152602090f35b3461017557600036600319011261017557604051631aab3f0d60e11b8152306004820152600060248201526020816044817f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b03165afa801561060f576102c0916000916108fa57506040519081529081906020820190565b610ecf36610b0d565b600080516020611d9383398151915254919290916001600160a01b03919060501c8216610f5357610eff81611cb6565b1691823b1561017557610f34926000928360405180968195829463064acaab60e11b8452602060048501526024840191611589565b03925af1801561060f57610f4457005b80610603610f5192610190565b005b60405162dc149f60e41b8152600490fd5b602036600319011261017557610f786103ee565b337f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b0316141580610fec575b61061457600080516020611d9383398151915290815469ffffffffffff000000004260201b169160e01c9069ffffffffffffffffffff191617179055600080f35b5030331415610fab565b346101755760a0366003190112610175576110126004356102fa565b61101d6024356102fa565b6084356001600160401b0381116101755761103c903690600401610316565b505060405163f23a6e6160e01b8152602090f35b63ffffffff60e01b166000527f439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dda602052604060002090565b600061109e81356001600160e01b031916611050565b5460601c337f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b03161415806110f2575b61061457818091368280378136915af43d82803e15610a9a573d90f35b506110fb611b20565b156110d5565b6002111561110b57565b634e487b7160e01b600052602160045260246000fd5b906004116101755790600490565b909291928360041161017557831161017557600401916003190190565b906024116101755760100190601490565b906058116101755760380190602090565b906024116101755760040190602090565b906038116101755760240190601490565b90600a116101755760040190600690565b9060101161017557600a0190600690565b90939293848311610175578411610175578101920390565b6001600160e01b031990358181169392600481106111e757505050565b60040360031b82901b16169150565b90816020910312610175575190565b606080825282516001600160a01b031690820152919392916040916112cb90602081015160808401528381015161124a610160918260a08701526101c0860190610250565b906112b861126a606085015193605f1994858983030160c08a0152610250565b608085015160e088015260a085015192610100938489015260c08601519061012091828a015260e08701519461014095868b0152870151908901528501518488830301610180890152610250565b92015190848303016101a0850152610250565b9460208201520152565b6040513d6000823e3d90fd5b6001600160a01b03939260009290918391907f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278987163303611529576004908135978861014481013501928060248501940135600080516020611d9383398151915254946113576113518383611121565b906111ca565b9b6001600160e01b0319808e16908161140c57505050899a9b50611386826020999a9b95949361139d9361112f565b9660501c965b858c806113fd575b505036916106d6565b6101408501526113c1604051998a9788968794633a871cdd60e01b86528501611205565b0393165af191821561060f5761073793926113dd575b50611d2c565b6113f691925060203d81116109215761091381836101de565b90386113d7565b81808092335af150858c611394565b9199509197969594939c8660e01b161615156000146114365760405163fc2f51c560e01b81528c90fd5b90899a9b91600160e09b95969798999a9b1b81146000146114d557506114776114726113518b606460209c9d0135016024868201359101611121565b611050565b60018101549099906001600160a01b031696848816156114ca575b508161139d926114a19261112f565b995460d081901b6001600160d01b03191660709190911b65ffffffffffff60a01b16179961138c565b60501c965081611492565b9198979095509250600160e11b0361151b5761151161139d948a9361150c6113518a606460209c01350160248d8201359101611121565b6115fe565b919992969161138c565b505050505050505050600190565b604051636b31ba1560e11b8152600490fd5b6bffffffffffffffffffffffff19903581811693926014811061155d57505050565b60140360031b82901b16169150565b35906020811061157a575090565b6000199060200360031b1b1690565b908060209392818452848401376000828201840152601f01601f1916010190565b604090610737949281528160208201520191611589565b6001600160d01b031990358181169392600681106115de57505050565b60060360031b82901b16169150565b916020610737938181520191611589565b9061162a61161e611618611612868561114c565b9061153b565b60601c90565b6001600160a01b031690565b9361163e611638858461115d565b9061156c565b60588301607882019461165961163887856058018a896111b2565b9661176261166a611638838961116e565b61167a611618611612858b61117f565b996117086116893689896106d6565b8051602091820120604080517f3ce406685c1b3551d706d85a68afdaa49ac4e07b451ad9b8ff8b58c3ee9641768185019081526001600160e01b03198b169282019290925260608101969096526001600160a01b039e909e16608086015260a08086019190915284529b8c9361170060c0826101de565b5190206118d9565b600080516020611d9383398151915254909190611744906117349060501c6001600160a01b031661161e565b9189019b60788d0190878d6111b2565b60405163199ed7c960e11b81529586948593849391600485016115aa565b03915afa92831561060f576114726117a861186895610517946000916118bc575b506117a1611791878d61116e565b6001600160a01b0319929161156c565b1690611d2c565b9a898b016078019a85036077190199611858906118486117e86117dd6117d76117d18b86611190565b906115c1565b60d01c90565b65ffffffffffff1690565b9761181f61161e6116186116126118086117dd6117d76117d1888b6111a1565b94611819611618611612838b61117f565b9761114c565b9461183961182b6101ff565b65ffffffffffff909b168b52565b89019065ffffffffffff169052565b6001600160a01b03166040870152565b6001600160a01b03166060850152565b6001600160a01b03871691823b156101755761189e926000928360405180968195829463064acaab60e11b8452600484016115ed565b03925af1801561060f576118af5750565b8061060361020c92610190565b6118d391508d803d106109215761091381836101de565b38611783565b7ff9f89debbb81ef022ec40582ee0279b0e86603696f5c9c3fd5a233f8e1520af97f000000000000000000000000f048ad83cb2dfd6037a43902a2a5be04e53cd2eb30147f000000000000000000000000000000000000000000000000000000000000000146141615611966575b671901000000000000600052601a52603a526042601820906000603a52565b5060a06040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f32ba20807d2fff2dbb34e0bcfa82982565bef566d4c0c633dc57b700b81c342760208201527f5709a9427ab590b580a826677786fd6b206c47e15c9470295fe07eeb734e6893604082015246606082015230608082015220611947565b600080516020611d9383398151915254611a3a93602093909291611a1c9060501c6001600160a01b031661161e565b916040519586948593849363199ed7c960e11b8552600485016115aa565b03915afa801561060f57611a5691600091611ab1575b50611d03565b9165ffffffffffff908142911611611aa15742911610611a94576001600160a01b0316611a8857630b135d3f60e11b90565b6001600160e01b031990565b506001600160e01b031990565b506001600160e01b031992915050565b611ac9915060203d81116109215761091381836101de565b38611a50565b90816020910312610175575180151581036101755790565b6001600160a01b0390911681526040602082018190528101829052606091806000848401376000828201840152601f01601f1916010190565b600080516020611d9383398151915254611b459060501c6001600160a01b031661161e565b6040519081639ea9bd5960e01b9182825260209384918180611b6b363360048401611ae7565b03915afa90811561060f57600091611c99575b50611c9257611b986000356001600160e01b031916611050565b6001810154909190611bb2906001600160a01b031661161e565b916001600160a01b03831615908115611c56575b8115611c32575b5015611bdb57505050600090565b829060405192839182528180611bf5363360048401611ae7565b03915afa91821561060f57600092611c0c57505090565b6107379250803d10611c2b575b611c2381836101de565b810190611acf565b503d611c19565b54611c45915065ffffffffffff166117dd565b65ffffffffffff4291161138611bcd565b905065ffffffffffff611c766117dd835465ffffffffffff9060301c1690565b168015159081611c88575b5090611bc6565b9050421138611c81565b5050600190565b611cb09150833d8511611c2b57611c2381836101de565b38611b7e565b600080516020611d9383398151915280547fffff0000000000000000000000000000000000000000ffffffffffffffffffff1660509290921b600160501b600160f01b0316919091179055565b8065ffffffffffff91828160a01c16928315600114611d24575b5060d01c92565b925038611d1d565b8082186001600160a01b031615600114611d47575050600190565b65ffffffffffff60a01b828116828216818118918111919091028082189465ffffffffffff60a01b199485169416929114611d8a575b5081811190821802181790565b925038611d7d56fe439ffe7df606b78489639bc0b827913bd09e1246fa6802968a5b3694c53e0dd9

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


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.