creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/WebAuthnValidator.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport {\n    IValidator,\n    IHook,\n    VALIDATION_SUCCESS,\n    VALIDATION_FAILED,\n    MODULE_TYPE_VALIDATOR,\n    MODULE_TYPE_HOOK\n} from \"kernel/interfaces/IERC7579Modules.sol\";\nimport {PackedUserOperation} from \"kernel/interfaces/PackedUserOperation.sol\";\nimport {SIG_VALIDATION_FAILED, ERC1271_MAGICVALUE, ERC1271_INVALID} from \"kernel/types/Constants.sol\";\nimport {WebAuthn} from \"./WebAuthn.sol\";\n\nstruct WebAuthnValidatorData {\n    uint256 pubKeyX;\n    uint256 pubKeyY;\n}\n\n/**\n * @title WebAuthnValidator\n * @notice This validator uses the P256 curve to validate signatures.\n */\ncontract WebAuthnValidator is IValidator {\n    // The location of the challenge in the clientDataJSON\n    uint256 constant CHALLENGE_LOCATION = 23;\n\n    // Emitted when a bad key is provided.\n    error InvalidPublicKey();\n\n    // Emitted when the public key of a kernel is changed.\n    event WebAuthnPublicKeyRegistered(\n        address indexed kernel, bytes32 indexed authenticatorIdHash, uint256 pubKeyX, uint256 pubKeyY\n    );\n\n    // The P256 public keys of a kernel.\n    mapping(address kernel => WebAuthnValidatorData WebAuthnValidatorData) public webAuthnValidatorStorage;\n\n    /**\n     * @notice Install WebAuthn validator for a kernel account.\n     * @dev The kernel account need to be the `msg.sender`.\n     * @dev The public key is encoded as `abi.encode(WebAuthnValidatorData)` inside the data, so (uint256,uint256).\n     * @dev The authenticatorIdHash is the hash of the authenticatorId. It enables to find public keys on-chain via event logs.\n     */\n    function onInstall(bytes calldata _data) external payable override {\n        // check if the webauthn validator is already initialized\n        if (_isInitialized(msg.sender)) revert AlreadyInitialized(msg.sender);\n        // check validity of the public key\n        (WebAuthnValidatorData memory webAuthnData, bytes32 authenticatorIdHash) =\n            abi.decode(_data, (WebAuthnValidatorData, bytes32));\n        if (webAuthnData.pubKeyX == 0 || webAuthnData.pubKeyY == 0) {\n            revert InvalidPublicKey();\n        }\n        // Update the key (so a sstore)\n        webAuthnValidatorStorage[msg.sender] = webAuthnData;\n        // And emit the event\n        emit WebAuthnPublicKeyRegistered(msg.sender, authenticatorIdHash, webAuthnData.pubKeyX, webAuthnData.pubKeyY);\n    }\n\n    /**\n     * @notice Uninstall WebAuthn validator for a kernel account.\n     * @dev The kernel account need to be the `msg.sender`.\n     */\n    function onUninstall(bytes calldata) external payable override {\n        if (!_isInitialized(msg.sender)) revert NotInitialized(msg.sender);\n        delete webAuthnValidatorStorage[msg.sender];\n    }\n\n    function isModuleType(uint256 typeID) external view override returns (bool) {\n        return typeID == MODULE_TYPE_VALIDATOR;\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 webAuthnValidatorStorage[smartAccount].pubKeyX != 0;\n    }\n\n    /**\n     * @notice Validate a user operation.\n     */\n    function validateUserOp(PackedUserOperation calldata _userOp, bytes32 _userOpHash)\n        external\n        payable\n        override\n        returns (uint256)\n    {\n        return _verifySignature(_userOp.sender, _userOpHash, _userOp.signature);\n    }\n\n    /**\n     * @notice Verify a signature with sender for ERC-1271 validation.\n     */\n    function isValidSignatureWithSender(address sender, bytes32 hash, bytes calldata data)\n        external\n        view\n        returns (bytes4)\n    {\n        return _verifySignature(sender, hash, data) == VALIDATION_SUCCESS ? ERC1271_MAGICVALUE : ERC1271_INVALID;\n    }\n\n    /**\n     * @notice Verify a signature.\n     */\n    function _verifySignature(address sender, bytes32 hash, bytes calldata signature) private view returns (uint256) {\n        // decode the signature\n        (\n            bytes memory authenticatorData,\n            string memory clientDataJSON,\n            uint256 responseTypeLocation,\n            uint256 r,\n            uint256 s,\n            bool usePrecompiled\n        ) = abi.decode(signature, (bytes, string, uint256, uint256, uint256, bool));\n\n        // get the public key from storage\n        WebAuthnValidatorData memory webAuthnData = webAuthnValidatorStorage[sender];\n\n        // verify the signature using the signature and the public key\n        bool isValid = WebAuthn.verifySignature(\n            abi.encodePacked(hash),\n            authenticatorData,\n            true,\n            clientDataJSON,\n            CHALLENGE_LOCATION,\n            responseTypeLocation,\n            r,\n            s,\n            webAuthnData.pubKeyX,\n            webAuthnData.pubKeyY,\n            usePrecompiled\n        );\n\n        // return the validation data\n        if (isValid) {\n            return VALIDATION_SUCCESS;\n        }\n\n        return VALIDATION_FAILED;\n    }\n}\n"
      },
      "lib/kernel_v3/src/interfaces/IERC7579Modules.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.21;\n\nimport {PackedUserOperation} from \"./PackedUserOperation.sol\";\n\nuint256 constant VALIDATION_SUCCESS = 0;\nuint256 constant VALIDATION_FAILED = 1;\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;\nuint256 constant MODULE_TYPE_ACTION = 7;\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    function preCheck(address msgSender, bytes calldata msgData) external payable returns (bytes memory hookData);\n    function postCheck(bytes calldata hookData) external payable returns (bool success);\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\ninterface IAction is IModule {}\n"
      },
      "lib/kernel_v3/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"
      },
      "lib/kernel_v3/src/types/Constants.sol": {
        "content": "pragma 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// Default CallType\n\nCallType constant CALLTYPE_SINGLE = CallType.wrap(0x00);\n// Batched CallType\nCallType constant CALLTYPE_BATCH = CallType.wrap(0x01);\n// @dev Implementing delegatecall is OPTIONAL!\n// implement delegatecall with extreme care.\nCallType constant CALLTYPE_DELEGATECALL = CallType.wrap(0xFF);\n\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\nExecModeSelector constant EXEC_MODE_DEFAULT = ExecModeSelector.wrap(bytes4(0x00000000));\n\nPassFlag constant SKIP_USEROP = PassFlag.wrap(0x0001);\nPassFlag constant SKIP_SIGNATURE = PassFlag.wrap(0x0002);\n\n// FLAG\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// TYPES, ENUM\nValidationType constant VALIDATION_TYPE_SUDO = ValidationType.wrap(0x00);\nValidationType constant VALIDATION_TYPE_VALIDATOR = ValidationType.wrap(0x01);\nValidationType constant VALIDATION_TYPE_PERMISSION = ValidationType.wrap(0x02);\n\n// ERC4337 constants\nuint256 constant SIG_VALIDATION_FAILED_UINT = 1;\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"
      },
      "src/WebAuthn.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./Base64URL.sol\";\nimport \"./P256.sol\";\n\n/**\n * Helper library for external contracts to verify WebAuthn signatures.\n *\n */\nlibrary WebAuthn {\n    /// Checks whether substr occurs in str starting at a given byte offset.\n    function contains(string memory substr, string memory str, uint256 location) internal pure returns (bool) {\n        bytes memory substrBytes = bytes(substr);\n        bytes memory strBytes = bytes(str);\n\n        uint256 substrLen = substrBytes.length;\n        uint256 strLen = strBytes.length;\n\n        for (uint256 i = 0; i < substrLen; i++) {\n            if (location + i >= strLen) {\n                return false;\n            }\n\n            if (substrBytes[i] != strBytes[location + i]) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    bytes1 constant AUTH_DATA_FLAGS_UP = 0x01; // Bit 0\n    bytes1 constant AUTH_DATA_FLAGS_UV = 0x04; // Bit 2\n    bytes1 constant AUTH_DATA_FLAGS_BE = 0x08; // Bit 3\n    bytes1 constant AUTH_DATA_FLAGS_BS = 0x10; // Bit 4\n\n    /// Verifies the authFlags in authenticatorData. Numbers in inline comment\n    /// correspond to the same numbered bullets in\n    /// https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion.\n    function checkAuthFlags(bytes1 flags, bool requireUserVerification) internal pure returns (bool) {\n        // 17. Verify that the UP bit of the flags in authData is set.\n        if (flags & AUTH_DATA_FLAGS_UP != AUTH_DATA_FLAGS_UP) {\n            return false;\n        }\n\n        // 18. If user verification was determined to be required, verify that\n        // the UV bit of the flags in authData is set. Otherwise, ignore the\n        // value of the UV flag.\n        if (requireUserVerification && (flags & AUTH_DATA_FLAGS_UV) != AUTH_DATA_FLAGS_UV) {\n            return false;\n        }\n\n        // 19. If the BE bit of the flags in authData is not set, verify that\n        // the BS bit is not set.\n        if (flags & AUTH_DATA_FLAGS_BE != AUTH_DATA_FLAGS_BE) {\n            if (flags & AUTH_DATA_FLAGS_BS == AUTH_DATA_FLAGS_BS) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Verifies a Webauthn P256 signature (Authentication Assertion) as described\n     * in https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion. We do not\n     * verify all the steps as described in the specification, only ones relevant\n     * to our context. Please carefully read through this list before usage.\n     * Specifically, we do verify the following:\n     * - Verify that authenticatorData (which comes from the authenticator,\n     *   such as iCloud Keychain) indicates a well-formed assertion. If\n     *   requireUserVerification is set, checks that the authenticator enforced\n     *   user verification. User verification should be required if,\n     *   and only if, options.userVerification is set to required in the request\n     * - Verifies that the client JSON is of type \"webauthn.get\", i.e. the client\n     *   was responding to a request to assert authentication.\n     * - Verifies that the client JSON contains the requested challenge.\n     * - Finally, verifies that (r, s) constitute a valid signature over both\n     *   the authenicatorData and client JSON, for public key (x, y).\n     *\n     * We make some assumptions about the particular use case of this verifier,\n     * so we do NOT verify the following:\n     * - Does NOT verify that the origin in the clientDataJSON matches the\n     *   Relying Party's origin: It is considered the authenticator's\n     *   responsibility to ensure that the user is interacting with the correct\n     *   RP. This is enforced by most high quality authenticators properly,\n     *   particularly the iCloud Keychain and Google Password Manager were\n     *   tested.\n     * - Does NOT verify That c.topOrigin is well-formed: We assume c.topOrigin\n     *   would never be present, i.e. the credentials are never used in a\n     *   cross-origin/iframe context. The website/app set up should disallow\n     *   cross-origin usage of the credentials. This is the default behaviour for\n     *   created credentials in common settings.\n     * - Does NOT verify that the rpIdHash in authData is the SHA-256 hash of an\n     *   RP ID expected by the Relying Party: This means that we rely on the\n     *   authenticator to properly enforce credentials to be used only by the\n     *   correct RP. This is generally enforced with features like Apple App Site\n     *   Association and Google Asset Links. To protect from edge cases in which\n     *   a previously-linked RP ID is removed from the authorised RP IDs,\n     *   we recommend that messages signed by the authenticator include some\n     *   expiry mechanism.\n     * - Does NOT verify the credential backup state: This assumes the credential\n     *   backup state is NOT used as part of Relying Party business logic or\n     *   policy.\n     * - Does NOT verify the values of the client extension outputs: This assumes\n     *   that the Relying Party does not use client extension outputs.\n     * - Does NOT verify the signature counter: Signature counters are intended\n     *   to enable risk scoring for the Relying Party. This assumes risk scoring\n     *   is not used as part of Relying Party business logic or policy.\n     * - Does NOT verify the attestation object: This assumes that\n     *   response.attestationObject is NOT present in the response, i.e. the\n     *   RP does not intend to verify an attestation.\n     */\n    function verifySignature(\n        bytes memory challenge,\n        bytes memory authenticatorData,\n        bool requireUserVerification,\n        string memory clientDataJSON,\n        uint256 challengeLocation,\n        uint256 responseTypeLocation,\n        uint256 r,\n        uint256 s,\n        uint256 x,\n        uint256 y,\n        bool usePrecompiled\n    ) internal view returns (bool) {\n        /// @notice defer the result to the end so dummy signature can go through all verification process including p256.verifySignature\n        bool deferredResult = true;\n\n        // Check that authenticatorData has good flags\n        if (authenticatorData.length < 37 || !checkAuthFlags(authenticatorData[32], requireUserVerification)) {\n            deferredResult = false;\n        }\n\n        // Check that response is for an authentication assertion\n        string memory responseType = '\"type\":\"webauthn.get\"';\n        if (!contains(responseType, clientDataJSON, responseTypeLocation)) {\n            deferredResult = false;\n        }\n\n        // Check that challenge is in the clientDataJSON\n        string memory challengeB64url = Base64URL.encode(challenge);\n        string memory challengeProperty = string.concat('\"challenge\":\"', challengeB64url, '\"');\n\n        if (!contains(challengeProperty, clientDataJSON, challengeLocation)) {\n            deferredResult = false;\n        }\n\n        // Check that the public key signed sha256(authenticatorData || sha256(clientDataJSON))\n        bytes32 clientDataJSONHash = sha256(bytes(clientDataJSON));\n        bytes32 messageHash = sha256(abi.encodePacked(authenticatorData, clientDataJSONHash));\n\n        // if responseTypeLocation is set to max, it means the signature is a dummy signature\n        if (responseTypeLocation == type(uint256).max) {\n            return P256.verifySignature(messageHash, r, s, x, y, false);\n        }\n\n        bool verified = P256.verifySignature(messageHash, r, s, x, y, usePrecompiled);\n\n        if (verified && deferredResult) {\n            return true;\n        }\n        return false;\n    }\n}\n"
      },
      "lib/kernel_v3/src/types/Types.sol": {
        "content": "pragma 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 {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 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"
      },
      "src/Base64URL.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"openzeppelin-contracts/contracts/utils/Base64.sol\";\n\nlibrary Base64URL {\n    function encode(bytes memory data) internal pure returns (string memory) {\n        string memory strb64 = Base64.encode(data);\n        bytes memory b64 = bytes(strb64);\n\n        // Base64 can end with \"=\" or \"==\"; Base64URL has no padding.\n        uint256 equalsCount = 0;\n        if (b64.length > 2 && b64[b64.length - 2] == \"=\") equalsCount = 2;\n        else if (b64.length > 1 && b64[b64.length - 1] == \"=\") equalsCount = 1;\n\n        uint256 len = b64.length - equalsCount;\n        bytes memory result = new bytes(len);\n\n        for (uint256 i = 0; i < len; i++) {\n            if (b64[i] == \"+\") {\n                result[i] = \"-\";\n            } else if (b64[i] == \"/\") {\n                result[i] = \"_\";\n            } else {\n                result[i] = b64[i];\n            }\n        }\n\n        return string(result);\n    }\n}\n"
      },
      "src/P256.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * Helper library for external contracts to verify P256 signatures.\n *\n */\nlibrary P256 {\n    address constant DAIMO_VERIFIER = 0xc2b78104907F722DABAc4C69f826a522B2754De4;\n    address constant PRECOMPILED_VERIFIER = 0x0000000000000000000000000000000000000100;\n\n    function verifySignatureAllowMalleability(\n        bytes32 message_hash,\n        uint256 r,\n        uint256 s,\n        uint256 x,\n        uint256 y,\n        bool usePrecompiled\n    ) internal view returns (bool) {\n        bytes memory args = abi.encode(message_hash, r, s, x, y);\n\n        if (usePrecompiled) {\n            (bool success, bytes memory ret) = PRECOMPILED_VERIFIER.staticcall(args);\n            if (success == false || ret.length == 0) {\n                return false;\n            }\n            return abi.decode(ret, (uint256)) == 1;\n        } else {\n            (, bytes memory ret) = DAIMO_VERIFIER.staticcall(args);\n            return abi.decode(ret, (uint256)) == 1;\n        }\n    }\n\n    /// P256 curve order n/2 for malleability check\n    uint256 constant P256_N_DIV_2 = 57896044605178124381348723474703786764998477612067880171211129530534256022184;\n\n    function verifySignature(bytes32 message_hash, uint256 r, uint256 s, uint256 x, uint256 y, bool usePrecompiled)\n        internal\n        view\n        returns (bool)\n    {\n        // check for signature malleability\n        if (s > P256_N_DIV_2) {\n            return false;\n        }\n\n        return verifySignatureAllowMalleability(message_hash, r, s, x, y, usePrecompiled);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Base64.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.2) (utils/Base64.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides a set of functions to operate with Base64 strings.\n */\nlibrary Base64 {\n    /**\n     * @dev Base64 Encoding/Decoding Table\n     * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648\n     */\n    string internal constant _TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n    string internal constant _TABLE_URL = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\n    /**\n     * @dev Converts a `bytes` to its Bytes64 `string` representation.\n     */\n    function encode(bytes memory data) internal pure returns (string memory) {\n        return _encode(data, _TABLE, true);\n    }\n\n    /**\n     * @dev Converts a `bytes` to its Bytes64Url `string` representation.\n     */\n    function encodeURL(bytes memory data) internal pure returns (string memory) {\n        return _encode(data, _TABLE_URL, false);\n    }\n\n    /**\n     * @dev Internal table-agnostic conversion\n     */\n    function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) {\n        /**\n         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\n         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\n         */\n        if (data.length == 0) return \"\";\n\n        // If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then\n        // multiplied by 4 so that it leaves room for padding the last chunk\n        // - `data.length + 2`  -> Round up\n        // - `/ 3`              -> Number of 3-bytes chunks\n        // - `4 *`              -> 4 characters for each chunk\n        // If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as\n        // opposed to when padding is required to fill the last chunk.\n        // - `4 *`              -> 4 characters for each chunk\n        // - `data.length + 2`  -> Round up\n        // - `/ 3`              -> Number of 3-bytes chunks\n        uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3;\n\n        string memory result = new string(resultLength);\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Prepare the lookup table (skip the first \"length\" byte)\n            let tablePtr := add(table, 1)\n\n            // Prepare result pointer, jump over length\n            let resultPtr := add(result, 0x20)\n            let dataPtr := data\n            let endPtr := add(data, mload(data))\n\n            // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and\n            // set it to zero to make sure no dirty bytes are read in that section.\n            let afterPtr := add(endPtr, 0x20)\n            let afterCache := mload(afterPtr)\n            mstore(afterPtr, 0x00)\n\n            // Run over the input, 3 bytes at a time\n            for {\n\n            } lt(dataPtr, endPtr) {\n\n            } {\n                // Advance 3 bytes\n                dataPtr := add(dataPtr, 3)\n                let input := mload(dataPtr)\n\n                // To write each character, shift the 3 byte (24 bits) chunk\n                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\n                // and apply logical AND with 0x3F to bitmask the least significant 6 bits.\n                // Use this as an index into the lookup table, mload an entire word\n                // so the desired character is in the least significant byte, and\n                // mstore8 this least significant byte into the result and continue.\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n            }\n\n            // Reset the value that was cached\n            mstore(afterPtr, afterCache)\n\n            if withPadding {\n                // When data `bytes` is not exactly 3 bytes long\n                // it is padded with `=` characters at the end\n                switch mod(mload(data), 3)\n                case 1 {\n                    mstore8(sub(resultPtr, 1), 0x3d)\n                    mstore8(sub(resultPtr, 2), 0x3d)\n                }\n                case 2 {\n                    mstore8(sub(resultPtr, 1), 0x3d)\n                }\n            }\n        }\n\n        return result;\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "ds-test/=lib/kernel_v3/lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "forge-std/=lib/forge-std/src/",
        "kernel/=lib/kernel_v3/src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "solady/=lib/kernel_v3/lib/solady/src/",
        "kernel_v3/=lib/kernel_v3/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": true,
      "libraries": {}
    }
  }}