creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/validator/ECDSAValidator.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport {ECDSA} from \"solady/utils/ECDSA.sol\";\nimport {IValidator, IHook} from \"../interfaces/IERC7579Modules.sol\";\nimport {PackedUserOperation} from \"../interfaces/PackedUserOperation.sol\";\nimport {\n    SIG_VALIDATION_SUCCESS_UINT,\n    SIG_VALIDATION_FAILED_UINT,\n    MODULE_TYPE_VALIDATOR,\n    MODULE_TYPE_HOOK,\n    ERC1271_MAGICVALUE,\n    ERC1271_INVALID\n} from \"../types/Constants.sol\";\n\nstruct ECDSAValidatorStorage {\n    address owner;\n}\n\ncontract ECDSAValidator is IValidator, IHook {\n    event OwnerRegistered(address indexed kernel, address indexed owner);\n\n    mapping(address => ECDSAValidatorStorage) public ecdsaValidatorStorage;\n\n    function onInstall(bytes calldata _data) external payable override {\n        if (_isInitialized(msg.sender)) revert AlreadyInitialized(msg.sender);\n        address owner = address(bytes20(_data[0:20]));\n        ecdsaValidatorStorage[msg.sender].owner = owner;\n        emit OwnerRegistered(msg.sender, owner);\n    }\n\n    function onUninstall(bytes calldata) external payable override {\n        if (!_isInitialized(msg.sender)) revert NotInitialized(msg.sender);\n        delete ecdsaValidatorStorage[msg.sender];\n    }\n\n    function isModuleType(uint256 typeID) external pure override returns (bool) {\n        return typeID == MODULE_TYPE_VALIDATOR || typeID == MODULE_TYPE_HOOK;\n    }\n\n    function isInitialized(address smartAccount) external view override returns (bool) {\n        return _isInitialized(smartAccount);\n    }\n\n    function _isInitialized(address smartAccount) internal view returns (bool) {\n        return ecdsaValidatorStorage[smartAccount].owner != address(0);\n    }\n\n    function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)\n        external\n        payable\n        override\n        returns (uint256)\n    {\n        address owner = ecdsaValidatorStorage[msg.sender].owner;\n        bytes calldata sig = userOp.signature;\n        if (owner == ECDSA.recover(userOpHash, sig)) {\n            return SIG_VALIDATION_SUCCESS_UINT;\n        }\n        bytes32 ethHash = ECDSA.toEthSignedMessageHash(userOpHash);\n        address recovered = ECDSA.recover(ethHash, sig);\n        if (owner != recovered) {\n            return SIG_VALIDATION_FAILED_UINT;\n        }\n        return SIG_VALIDATION_SUCCESS_UINT;\n    }\n\n    function isValidSignatureWithSender(address, bytes32 hash, bytes calldata sig)\n        external\n        view\n        override\n        returns (bytes4)\n    {\n        address owner = ecdsaValidatorStorage[msg.sender].owner;\n        if (owner == ECDSA.recover(hash, sig)) {\n            return ERC1271_MAGICVALUE;\n        }\n        bytes32 ethHash = ECDSA.toEthSignedMessageHash(hash);\n        address recovered = ECDSA.recover(ethHash, sig);\n        if (owner != recovered) {\n            return ERC1271_INVALID;\n        }\n        return ERC1271_MAGICVALUE;\n    }\n\n    function preCheck(address msgSender, uint256 value, bytes calldata)\n        external\n        payable\n        override\n        returns (bytes memory)\n    {\n        require(msgSender == ecdsaValidatorStorage[msg.sender].owner, \"ECDSAValidator: sender is not owner\");\n        return hex\"\";\n    }\n\n    function postCheck(bytes calldata hookData, bool success, bytes calldata res) external payable override {}\n}\n"
      },
      "lib/solady/src/utils/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Gas optimized ECDSA wrapper.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)\n///\n/// @dev Note:\n/// - The recovery functions use the ecrecover precompile (0x1).\n/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.\n///   This is for more safety by default.\n///   Use the `tryRecover` variants if you need to get the zero address back\n///   upon recovery failure instead.\n/// - As of Solady version 0.0.134, all `bytes signature` variants accept both\n///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.\n///   See: https://eips.ethereum.org/EIPS/eip-2098\n///   This is for calldata efficiency on smart accounts prevalent on L2s.\n///\n/// WARNING! Do NOT use signatures as unique identifiers:\n/// - Use a nonce in the digest to prevent replay attacks on the same contract.\n/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.\n///   EIP-712 also enables readable signing of typed data for better user safety.\n/// This implementation does NOT check if a signature is non-malleable.\nlibrary ECDSA {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                        CUSTOM ERRORS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The signature is invalid.\n    error InvalidSignature();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                    RECOVERY OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\n    function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := 1\n            let m := mload(0x40) // Cache the free memory pointer.\n            for {} 1 {} {\n                mstore(0x00, hash)\n                mstore(0x40, mload(add(signature, 0x20))) // `r`.\n                if eq(mload(signature), 64) {\n                    let vs := mload(add(signature, 0x40))\n                    mstore(0x20, add(shr(255, vs), 27)) // `v`.\n                    mstore(0x60, shr(1, shl(1, vs))) // `s`.\n                    break\n                }\n                if eq(mload(signature), 65) {\n                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\n                    mstore(0x60, mload(add(signature, 0x40))) // `s`.\n                    break\n                }\n                result := 0\n                break\n            }\n            result :=\n                mload(\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        result, // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                )\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            if iszero(returndatasize()) {\n                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\n    function recoverCalldata(bytes32 hash, bytes calldata signature)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := 1\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            for {} 1 {} {\n                if eq(signature.length, 64) {\n                    let vs := calldataload(add(signature.offset, 0x20))\n                    mstore(0x20, add(shr(255, vs), 27)) // `v`.\n                    mstore(0x40, calldataload(signature.offset)) // `r`.\n                    mstore(0x60, shr(1, shl(1, vs))) // `s`.\n                    break\n                }\n                if eq(signature.length, 65) {\n                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\n                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.\n                    break\n                }\n                result := 0\n                break\n            }\n            result :=\n                mload(\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        result, // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                )\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            if iszero(returndatasize()) {\n                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the EIP-2098 short form signature defined by `r` and `vs`.\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, add(shr(255, vs), 27)) // `v`.\n            mstore(0x40, r)\n            mstore(0x60, shr(1, shl(1, vs))) // `s`.\n            result :=\n                mload(\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        1, // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                )\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            if iszero(returndatasize()) {\n                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the signature defined by `v`, `r`, `s`.\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, and(v, 0xff))\n            mstore(0x40, r)\n            mstore(0x60, s)\n            result :=\n                mload(\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        1, // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                )\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            if iszero(returndatasize()) {\n                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   TRY-RECOVER OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // WARNING!\n    // These functions will NOT revert upon recovery failure.\n    // Instead, they will return the zero address upon recovery failure.\n    // It is critical that the returned address is NEVER compared against\n    // a zero address (e.g. an uninitialized address variable).\n\n    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\n    function tryRecover(bytes32 hash, bytes memory signature)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := 1\n            let m := mload(0x40) // Cache the free memory pointer.\n            for {} 1 {} {\n                mstore(0x00, hash)\n                mstore(0x40, mload(add(signature, 0x20))) // `r`.\n                if eq(mload(signature), 64) {\n                    let vs := mload(add(signature, 0x40))\n                    mstore(0x20, add(shr(255, vs), 27)) // `v`.\n                    mstore(0x60, shr(1, shl(1, vs))) // `s`.\n                    break\n                }\n                if eq(mload(signature), 65) {\n                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\n                    mstore(0x60, mload(add(signature, 0x40))) // `s`.\n                    break\n                }\n                result := 0\n                break\n            }\n            pop(\n                staticcall(\n                    gas(), // Amount of gas left for the transaction.\n                    result, // Address of `ecrecover`.\n                    0x00, // Start of input.\n                    0x80, // Size of input.\n                    0x40, // Start of output.\n                    0x20 // Size of output.\n                )\n            )\n            mstore(0x60, 0) // Restore the zero slot.\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            result := mload(xor(0x60, returndatasize()))\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\n    function tryRecoverCalldata(bytes32 hash, bytes calldata signature)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := 1\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            for {} 1 {} {\n                if eq(signature.length, 64) {\n                    let vs := calldataload(add(signature.offset, 0x20))\n                    mstore(0x20, add(shr(255, vs), 27)) // `v`.\n                    mstore(0x40, calldataload(signature.offset)) // `r`.\n                    mstore(0x60, shr(1, shl(1, vs))) // `s`.\n                    break\n                }\n                if eq(signature.length, 65) {\n                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\n                    calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.\n                    break\n                }\n                result := 0\n                break\n            }\n            pop(\n                staticcall(\n                    gas(), // Amount of gas left for the transaction.\n                    result, // Address of `ecrecover`.\n                    0x00, // Start of input.\n                    0x80, // Size of input.\n                    0x40, // Start of output.\n                    0x20 // Size of output.\n                )\n            )\n            mstore(0x60, 0) // Restore the zero slot.\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            result := mload(xor(0x60, returndatasize()))\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the EIP-2098 short form signature defined by `r` and `vs`.\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, add(shr(255, vs), 27)) // `v`.\n            mstore(0x40, r)\n            mstore(0x60, shr(1, shl(1, vs))) // `s`.\n            pop(\n                staticcall(\n                    gas(), // Amount of gas left for the transaction.\n                    1, // Address of `ecrecover`.\n                    0x00, // Start of input.\n                    0x80, // Size of input.\n                    0x40, // Start of output.\n                    0x20 // Size of output.\n                )\n            )\n            mstore(0x60, 0) // Restore the zero slot.\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            result := mload(xor(0x60, returndatasize()))\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the signature defined by `v`, `r`, `s`.\n    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, and(v, 0xff))\n            mstore(0x40, r)\n            mstore(0x60, s)\n            pop(\n                staticcall(\n                    gas(), // Amount of gas left for the transaction.\n                    1, // Address of `ecrecover`.\n                    0x00, // Start of input.\n                    0x80, // Size of input.\n                    0x40, // Start of output.\n                    0x20 // Size of output.\n                )\n            )\n            mstore(0x60, 0) // Restore the zero slot.\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            result := mload(xor(0x60, returndatasize()))\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     HASHING OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns an Ethereum Signed Message, created from a `hash`.\n    /// This produces a hash corresponding to the one signed with the\n    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\n    /// JSON-RPC method as part of EIP-191.\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x20, hash) // Store into scratch space for keccak256.\n            mstore(0x00, \"\\x00\\x00\\x00\\x00\\x19Ethereum Signed Message:\\n32\") // 28 bytes.\n            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.\n        }\n    }\n\n    /// @dev Returns an Ethereum Signed Message, created from `s`.\n    /// This produces a hash corresponding to the one signed with the\n    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\n    /// JSON-RPC method as part of EIP-191.\n    /// Note: Supports lengths of `s` up to 999999 bytes.\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let sLength := mload(s)\n            let o := 0x20\n            mstore(o, \"\\x19Ethereum Signed Message:\\n\") // 26 bytes, zero-right-padded.\n            mstore(0x00, 0x00)\n            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.\n            for { let temp := sLength } 1 {} {\n                o := sub(o, 1)\n                mstore8(o, add(48, mod(temp, 10)))\n                temp := div(temp, 10)\n                if iszero(temp) { break }\n            }\n            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.\n            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.\n            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))\n            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.\n            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))\n            mstore(s, sLength) // Restore the length.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   EMPTY CALLDATA HELPERS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns an empty calldata bytes.\n    function emptySignature() internal pure returns (bytes calldata signature) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            signature.length := 0\n        }\n    }\n}\n"
      },
      "src/interfaces/IERC7579Modules.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.21;\n\nimport {PackedUserOperation} from \"./PackedUserOperation.sol\";\n\ninterface IModule {\n    error AlreadyInitialized(address smartAccount);\n    error NotInitialized(address smartAccount);\n\n    /**\n     * @dev This function is called by the smart account during installation of the module\n     * @param data arbitrary data that may be required on the module during `onInstall`\n     * initialization\n     *\n     * MUST revert on error (i.e. if module is already enabled)\n     */\n    function onInstall(bytes calldata data) external payable;\n\n    /**\n     * @dev This function is called by the smart account during uninstallation of the module\n     * @param data arbitrary data that may be required on the module during `onUninstall`\n     * de-initialization\n     *\n     * MUST revert on error\n     */\n    function onUninstall(bytes calldata data) external payable;\n\n    /**\n     * @dev Returns boolean value if module is a certain type\n     * @param moduleTypeId the module type ID according the ERC-7579 spec\n     *\n     * MUST return true if the module is of the given type and false otherwise\n     */\n    function isModuleType(uint256 moduleTypeId) external view returns (bool);\n\n    /**\n     * @dev Returns if the module was already initialized for a provided smartaccount\n     */\n    function isInitialized(address smartAccount) external view returns (bool);\n}\n\ninterface IValidator is IModule {\n    error InvalidTargetAddress(address target);\n\n    /**\n     * @dev Validates a transaction on behalf of the account.\n     *         This function is intended to be called by the MSA during the ERC-4337 validaton phase\n     *         Note: solely relying on bytes32 hash and signature is not suffcient for some\n     * validation implementations (i.e. SessionKeys often need access to userOp.calldata)\n     * @param userOp The user operation to be validated. The userOp MUST NOT contain any metadata.\n     * The MSA MUST clean up the userOp before sending it to the validator.\n     * @param userOpHash The hash of the user operation to be validated\n     * @return return value according to ERC-4337\n     */\n    function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)\n        external\n        payable\n        returns (uint256);\n\n    /**\n     * Validator can be used for ERC-1271 validation\n     */\n    function isValidSignatureWithSender(address sender, bytes32 hash, bytes calldata data)\n        external\n        view\n        returns (bytes4);\n}\n\ninterface IExecutor is IModule {}\n\ninterface IHook is IModule {\n    /**\n     * @dev Called by the smart account before execution\n     * @param msgSender the address that called the smart account\n     * @param value the value that was sent to the smart account\n     * @param msgData the data that was sent to the smart account\n     *\n     * MAY return arbitrary data in the `hookData` return value\n     */\n    function preCheck(address msgSender, uint256 value, bytes calldata msgData)\n        external\n        payable\n        returns (bytes memory hookData);\n\n    /**\n     * @dev Called by the smart account after execution\n     * @param hookData the data that was returned by the `preCheck` function\n     * @param executionSuccess whether the execution(s) was (were) successful\n     * @param executionReturn the return/revert data of the execution(s)\n     *\n     * MAY validate the `hookData` to validate transaction context of the `preCheck` function\n     */\n    function postCheck(bytes calldata hookData, bool executionSuccess, bytes calldata executionReturn)\n        external\n        payable;\n}\n\ninterface IFallback is IModule {}\n\ninterface IPolicy is IModule {\n    function checkUserOpPolicy(bytes32 id, PackedUserOperation calldata userOp) external payable returns (uint256);\n    function checkSignaturePolicy(bytes32 id, address sender, bytes32 hash, bytes calldata sig)\n        external\n        view\n        returns (uint256);\n}\n\ninterface ISigner is IModule {\n    function checkUserOpSignature(bytes32 id, PackedUserOperation calldata userOp, bytes32 userOpHash)\n        external\n        payable\n        returns (uint256);\n    function checkSignature(bytes32 id, address sender, bytes32 hash, bytes calldata sig)\n        external\n        view\n        returns (bytes4);\n}\n"
      },
      "src/interfaces/PackedUserOperation.sol": {
        "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity >=0.7.5;\n\n/**\n * User Operation struct\n * @param sender                - The sender account of this request.\n * @param nonce                 - Unique value the sender uses to verify it is not a replay.\n * @param initCode              - If set, the account contract will be created by this constructor/\n * @param callData              - The method call to execute on this account.\n * @param accountGasLimits      - Packed gas limits for validateUserOp and gas limit passed to the callData method call.\n * @param preVerificationGas    - Gas not calculated by the handleOps method, but added to the gas paid.\n *                                Covers batch overhead.\n * @param gasFees                - packed gas fields maxFeePerGas and maxPriorityFeePerGas - Same as EIP-1559 gas parameter.\n * @param paymasterAndData      - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data\n *                                The paymaster will pay for the transaction instead of the sender.\n * @param signature             - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\nstruct PackedUserOperation {\n    address sender;\n    uint256 nonce;\n    bytes initCode;\n    bytes callData;\n    bytes32 accountGasLimits;\n    uint256 preVerificationGas;\n    bytes32 gasFees; //maxPriorityFee and maxFeePerGas;\n    bytes paymasterAndData;\n    bytes signature;\n}\n"
      },
      "src/types/Constants.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport {CallType, ExecType, ExecModeSelector} from \"./Types.sol\";\nimport {PassFlag, ValidationMode, ValidationType} from \"./Types.sol\";\nimport {ValidationData} from \"./Types.sol\";\n\n// --- ERC7579 calltypes ---\n// Default CallType\nCallType constant CALLTYPE_SINGLE = CallType.wrap(0x00);\n// Batched CallType\nCallType constant CALLTYPE_BATCH = CallType.wrap(0x01);\nCallType constant CALLTYPE_STATIC = CallType.wrap(0xFE);\n// @dev Implementing delegatecall is OPTIONAL!\n// implement delegatecall with extreme care.\nCallType constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF);\n\n// --- ERC7579 exectypes ---\n// @dev default behavior is to revert on failure\n// To allow very simple accounts to use mode encoding, the default behavior is to revert on failure\n// Since this is value 0x00, no additional encoding is required for simple accounts\nExecType constant EXECTYPE_DEFAULT = ExecType.wrap(0x00);\n// @dev account may elect to change execution behavior. For example \"try exec\" / \"allow fail\"\nExecType constant EXECTYPE_TRY = ExecType.wrap(0x01);\n\n// --- ERC7579 mode selector ---\nExecModeSelector constant EXEC_MODE_DEFAULT = ExecModeSelector.wrap(bytes4(0x00000000));\n\n// --- Kernel permission skip flags ---\nPassFlag constant SKIP_USEROP = PassFlag.wrap(0x0001);\nPassFlag constant SKIP_SIGNATURE = PassFlag.wrap(0x0002);\n\n// --- Kernel validation modes ---\nValidationMode constant VALIDATION_MODE_DEFAULT = ValidationMode.wrap(0x00);\nValidationMode constant VALIDATION_MODE_ENABLE = ValidationMode.wrap(0x01);\nValidationMode constant VALIDATION_MODE_INSTALL = ValidationMode.wrap(0x02);\n\n// --- Kernel validation types ---\nValidationType constant VALIDATION_TYPE_ROOT = ValidationType.wrap(0x00);\nValidationType constant VALIDATION_TYPE_VALIDATOR = ValidationType.wrap(0x01);\nValidationType constant VALIDATION_TYPE_PERMISSION = ValidationType.wrap(0x02);\n\n// --- storage slots ---\n// bytes32(uint256(keccak256('kernel.v3.selector')) - 1)\nbytes32 constant SELECTOR_MANAGER_STORAGE_SLOT = 0x7c341349a4360fdd5d5bc07e69f325dc6aaea3eb018b3e0ea7e53cc0bb0d6f3b;\n// bytes32(uint256(keccak256('kernel.v3.executor')) - 1)\nbytes32 constant EXECUTOR_MANAGER_STORAGE_SLOT = 0x1bbee3173dbdc223633258c9f337a0fff8115f206d302bea0ed3eac003b68b86;\n// bytes32(uint256(keccak256('kernel.v3.hook')) - 1)\nbytes32 constant HOOK_MANAGER_STORAGE_SLOT = 0x4605d5f70bb605094b2e761eccdc27bed9a362d8612792676bf3fb9b12832ffc;\n// bytes32(uint256(keccak256('kernel.v3.validation')) - 1)\nbytes32 constant VALIDATION_MANAGER_STORAGE_SLOT = 0x7bcaa2ced2a71450ed5a9a1b4848e8e5206dbc3f06011e595f7f55428cc6f84f;\nbytes32 constant ERC1967_IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n// --- Kernel validation nonce incremental size limit ---\nuint32 constant MAX_NONCE_INCREMENT_SIZE = 10;\n\n// -- EIP712 type hash ---\nbytes32 constant ENABLE_TYPE_HASH = 0xb17ab1224aca0d4255ef8161acaf2ac121b8faa32a4b2258c912cc5f8308c505;\nbytes32 constant KERNEL_WRAPPER_TYPE_HASH = 0x1547321c374afde8a591d972a084b071c594c275e36724931ff96c25f2999c83;\n\n// --- ERC constants ---\n// ERC4337 constants\nuint256 constant SIG_VALIDATION_FAILED_UINT = 1;\nuint256 constant SIG_VALIDATION_SUCCESS_UINT = 0;\nValidationData constant SIG_VALIDATION_FAILED = ValidationData.wrap(SIG_VALIDATION_FAILED_UINT);\n\n// ERC-1271 constants\nbytes4 constant ERC1271_MAGICVALUE = 0x1626ba7e;\nbytes4 constant ERC1271_INVALID = 0xffffffff;\n\nuint256 constant MODULE_TYPE_VALIDATOR = 1;\nuint256 constant MODULE_TYPE_EXECUTOR = 2;\nuint256 constant MODULE_TYPE_FALLBACK = 3;\nuint256 constant MODULE_TYPE_HOOK = 4;\nuint256 constant MODULE_TYPE_POLICY = 5;\nuint256 constant MODULE_TYPE_SIGNER = 6;\n"
      },
      "src/types/Types.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.23;\n\n// Custom type for improved developer experience\ntype ExecMode is bytes32;\n\ntype CallType is bytes1;\n\ntype ExecType is bytes1;\n\ntype ExecModeSelector is bytes4;\n\ntype ExecModePayload is bytes22;\n\nusing {eqModeSelector as ==} for ExecModeSelector global;\nusing {eqCallType as ==} for CallType global;\nusing {notEqCallType as !=} for CallType global;\nusing {eqExecType as ==} for ExecType global;\n\nfunction eqCallType(CallType a, CallType b) pure returns (bool) {\n    return CallType.unwrap(a) == CallType.unwrap(b);\n}\n\nfunction notEqCallType(CallType a, CallType b) pure returns (bool) {\n    return CallType.unwrap(a) != CallType.unwrap(b);\n}\n\nfunction eqExecType(ExecType a, ExecType b) pure returns (bool) {\n    return ExecType.unwrap(a) == ExecType.unwrap(b);\n}\n\nfunction eqModeSelector(ExecModeSelector a, ExecModeSelector b) pure returns (bool) {\n    return ExecModeSelector.unwrap(a) == ExecModeSelector.unwrap(b);\n}\n\ntype ValidationMode is bytes1;\n\ntype ValidationId is bytes21;\n\ntype ValidationType is bytes1;\n\ntype PermissionId is bytes4;\n\ntype PolicyData is bytes22; // 2bytes for flag on skip, 20 bytes for validator address\n\ntype PassFlag is bytes2;\n\nusing {vModeEqual as ==} for ValidationMode global;\nusing {vTypeEqual as ==} for ValidationType global;\nusing {vIdentifierEqual as ==} for ValidationId global;\nusing {vModeNotEqual as !=} for ValidationMode global;\nusing {vTypeNotEqual as !=} for ValidationType global;\nusing {vIdentifierNotEqual as !=} for ValidationId global;\n\n// nonce = uint192(key) + nonce\n// key = mode + (vtype + validationDataWithoutType) + 2bytes parallelNonceKey\n// key = 0x00 + 0x00 + 0x000 .. 00 + 0x0000\n// key = 0x00 + 0x01 + 0x1234...ff + 0x0000\n// key = 0x00 + 0x02 + ( ) + 0x000\n\nfunction vModeEqual(ValidationMode a, ValidationMode b) pure returns (bool) {\n    return ValidationMode.unwrap(a) == ValidationMode.unwrap(b);\n}\n\nfunction vModeNotEqual(ValidationMode a, ValidationMode b) pure returns (bool) {\n    return ValidationMode.unwrap(a) != ValidationMode.unwrap(b);\n}\n\nfunction vTypeEqual(ValidationType a, ValidationType b) pure returns (bool) {\n    return ValidationType.unwrap(a) == ValidationType.unwrap(b);\n}\n\nfunction vTypeNotEqual(ValidationType a, ValidationType b) pure returns (bool) {\n    return ValidationType.unwrap(a) != ValidationType.unwrap(b);\n}\n\nfunction vIdentifierEqual(ValidationId a, ValidationId b) pure returns (bool) {\n    return ValidationId.unwrap(a) == ValidationId.unwrap(b);\n}\n\nfunction vIdentifierNotEqual(ValidationId a, ValidationId b) pure returns (bool) {\n    return ValidationId.unwrap(a) != ValidationId.unwrap(b);\n}\n\ntype ValidationData is uint256;\n\ntype ValidAfter is uint48;\n\ntype ValidUntil is uint48;\n\nfunction getValidationResult(ValidationData validationData) pure returns (address result) {\n    assembly {\n        result := validationData\n    }\n}\n\nfunction packValidationData(ValidAfter validAfter, ValidUntil validUntil) pure returns (uint256) {\n    return uint256(ValidAfter.unwrap(validAfter)) << 208 | uint256(ValidUntil.unwrap(validUntil)) << 160;\n}\n\nfunction parseValidationData(uint256 validationData)\n    pure\n    returns (ValidAfter validAfter, ValidUntil validUntil, address result)\n{\n    assembly {\n        result := validationData\n        validUntil := and(shr(160, validationData), 0xffffffffffff)\n        switch iszero(validUntil)\n        case 1 { validUntil := 0xffffffffffff }\n        validAfter := shr(208, validationData)\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "ExcessivelySafeCall/=lib/ExcessivelySafeCall/src/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "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": {}
    }
  }}