diff --git a/deployments/arbitrum_production/.chainId b/deployments/arbitrum_production/.chainId new file mode 100644 index 0000000..7df83ec --- /dev/null +++ b/deployments/arbitrum_production/.chainId @@ -0,0 +1 @@ +42161 \ No newline at end of file diff --git a/deployments/arbitrum_production/P256Signer.json b/deployments/arbitrum_production/P256Signer.json new file mode 100644 index 0000000..3cb288e --- /dev/null +++ b/deployments/arbitrum_production/P256Signer.json @@ -0,0 +1,275 @@ +{ + "address": "0x93ae54DAE3A266d2F7197d118e1B3A89429ba55F", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHash", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "y_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "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": [ + { + "internalType": "bytes", + "name": "_hash", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "x", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "y", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x6fd66c9eb3c41cb8a595640f91879ede150ecfaee7d1e89c3b1c52521c54bada", + "receipt": { + "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", + "from": "0x61f2ad863873d2466B64cef9cdC65361F98A65D3", + "contractAddress": null, + "transactionIndex": 17, + "gasUsed": "2484397", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf234a9d3639922d48fe8dcc3474abb5f185f47080112259a9dbfa61be00e2fdb", + "transactionHash": "0x6fd66c9eb3c41cb8a595640f91879ede150ecfaee7d1e89c3b1c52521c54bada", + "logs": [], + "blockNumber": 194762992, + "cumulativeGasUsed": "5346735", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "01c9a206ce5ca6951fd356b6a1b5a7d7", + "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAuthenticatorData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidClientData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidHash\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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\":[{\"internalType\":\"bytes\",\"name\":\"_hash\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"isValidSignature\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"y\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract is the implementation. It is meant to be used through proxy clone.\",\"kind\":\"dev\",\"methods\":{\"initialize(uint256,uint256)\":{\"details\":\"This function is only callable once and needs to be called immediately after deployment by the factory in the same transaction.\",\"params\":{\"x_\":\"The x coordinate of the public key\",\"y_\":\"The y coordinate of the public key\"}},\"isValidSignature(bytes,bytes)\":{\"details\":\"This is the old version of the function of EIP-1271 using bytes memory instead of bytes32\",\"params\":{\"_hash\":\"The hash of the data signed\",\"_signature\":\"The signature\"},\"returns\":{\"_0\":\"The EIP-1271 magic value\"}},\"isValidSignature(bytes32,bytes)\":{\"params\":{\"_hash\":\"The hash of the data signed\",\"_signature\":\"The signature\"},\"returns\":{\"_0\":\"The EIP-1271 magic value\"}}},\"title\":\"P256Signer\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInitialized()\":[{\"notice\":\"Error message when the contract is already initialized\"}],\"InvalidHash()\":[{\"notice\":\"Error message when the hash is invalid\"}],\"InvalidSignature()\":[{\"notice\":\"Error message when the signature is invalid\"}]},\"kind\":\"user\",\"methods\":{\"initialized()\":{\"notice\":\"Whether the contract has been initialized\"},\"isValidSignature(bytes,bytes)\":{\"notice\":\"Verifies that the signer is the owner of the secp256r1 public key.\"},\"isValidSignature(bytes32,bytes)\":{\"notice\":\"Verifies that the signer is the owner of the secp256r1 public key.\"},\"x()\":{\"notice\":\"The x coordinate of the secp256r1 public key\"},\"y()\":{\"notice\":\"The y coordinate of the secp256r1 public key\"}},\"notice\":\"A contract used to verify ECDSA signatures over secp256r1 through EIP-1271 of Webauthn payloads.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/P256Signer.sol\":\"P256Signer\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"FreshCryptoLib/FCL_Webauthn.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_elliptic.sol\\n///*\\n///*\\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\nimport {FCL_ecdsa} from \\\"./FCL_ecdsa.sol\\\";\\n\\nimport {FCL_ecdsa_utils} from \\\"./FCL_ecdsa_utils.sol\\\";\\n\\nlibrary FCL_WebAuthn {\\n error InvalidAuthenticatorData();\\n error InvalidClientData();\\n error InvalidSignature();\\n\\n function WebAuthn_format(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata // rs\\n ) internal pure returns (bytes32 result) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n {\\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\\n revert InvalidAuthenticatorData();\\n }\\n // Verify that clientData commits to the expected client challenge\\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\\n bytes memory challengeExtracted = new bytes(\\n bytes(challengeEncoded).length\\n );\\n\\n assembly {\\n calldatacopy(\\n add(challengeExtracted, 32),\\n add(clientData.offset, clientChallengeDataOffset),\\n mload(challengeExtracted)\\n )\\n }\\n\\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\\n assembly {\\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\\n }\\n\\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\\n revert InvalidClientData();\\n }\\n } //avoid stack full\\n\\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\\n\\n assembly {\\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\\n }\\n\\n bytes32 more = sha256(clientData);\\n assembly {\\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\\n }\\n\\n return sha256(verifyData);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256[2] calldata Q\\n ) internal view returns (bool) {\\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 Qx,\\n uint256 Qy\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\\n\\n return result;\\n }\\n\\n function checkSignature_prec(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n address dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\\n\\n return result;\\n }\\n\\n //beware that this implementation will not be compliant with EOF\\n function checkSignature_hackmem(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc2811ef6e17ea1d5509a3d3f7d5af5e56583347b36093d05530425d7c1316dd6\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n /**\\n * @dev ECDSA verification, given , signature, and public key, no calldata version\\n */\\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\\n\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n \\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n\\n x1= addmod(x1, n-r,n );\\n \\n return x1 == 0;\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n \\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n}\\n\",\"keccak256\":\"0x679d2e9a655cd7e156a0cfc24de0aca88d4e0b34a8e0dfe6a599f23af092f5a2\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa_utils.sol\":{\"content\":\"\\n//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa_utils {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n x1= addmod(x1, n-r,n );\\n \\n \\n return x1 == 0;\\n }\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\n return ecdsa_verify(message, rs, Q[0], Q[1]);\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n\\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\\n //K is nonce, kpriv is private key\\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\\n {\\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \\n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n //ecdsa key derivation\\n //kpriv is private key return (x,y) coordinates of associated Pubkey\\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\\n {\\n \\n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\\n \\n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\\n {\\n y=FCL_Elliptic_ZZ.p-y;\\n } \\n\\n }\\n \\n //precomputations for 8 dimensional trick\\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\\n {\\n \\n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\\n \\n //the trivial private keys 1 and -1 are forbidden\\n if(Qx==FCL_Elliptic_ZZ.gx)\\n {\\n revert();\\n }\\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\\n \\n Pow64_PQ[4][0]=Qx;\\n Pow64_PQ[4][1]=Qy;\\n \\n /* raise to multiplication by 64 by 6 consecutive doubling*/\\n for(uint j=1;j<4;j++){\\n uint256 x;\\n uint256 y;\\n uint256 zz;\\n uint256 zzz;\\n \\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\\n \\t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\\n \\t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n\\n \\tfor(uint i=0;i<63;i++){\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t}\\n }\\n \\n /* neutral point */\\n Prec[0][0]=0;\\n Prec[0][1]=0;\\n \\n \\t\\n for(uint i=1;i<256;i++)\\n { \\n Prec[i][0]=0;\\n Prec[i][1]=0;\\n \\n for(uint j=0;j<8;j++)\\n {\\n \\tif( (i&(1<=0.8.19 <0.9.0;\\n\\nlibrary FCL_Elliptic_ZZ {\\n // Set parameters for curve sec256r1.\\n\\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\\n //curve prime field modulus\\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n //short weierstrass first coefficient\\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n //short weierstrass second coefficient\\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n //generating point affine coordinates\\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n //curve order (number of points)\\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\\n /* -2 mod n constant, used to speed up inversion*/\\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\\n\\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n //P+1 div 4\\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\\n //arbitrary constant to express no quadratic residuosity\\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n /**\\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\\n */\\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2modn)\\n mstore(add(pointer, 0xa0), n)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n /**\\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\\n */\\n\\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2)\\n mstore(add(pointer, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n\\n //Coron projective shuffling, take as input alpha as blinding factor\\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n \\n uint256 alpha2=mulmod(alpha,alpha,p);\\n \\n x3=mulmod(alpha2, x,p); //alpha^-2.x\\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\\n\\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\\n \\n return (x3, y3, zz3, zzz3);\\n }\\n\\n\\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\\n u2=addmod(u2, p-u1, p);// P = U2-U1\\n x1=mulmod(u2, u2, p);//PP\\n x2=mulmod(x1, u2, p);//PPP\\n \\n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \\n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\\n\\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \\n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\\n\\n return (x3, y3, zz3, zzz3);\\n }\\n\\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\\n/// @param self The integer of which to find the modular inverse\\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\\n\\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\\n assembly (\\\"memory-safe\\\") {\\n // load the free memory pointer value\\n let pointer := mload(0x40)\\n\\n // Define length of base (Bsize)\\n mstore(pointer, 0x20)\\n // Define the exponent size (Esize)\\n mstore(add(pointer, 0x20), 0x20)\\n // Define the modulus size (Msize)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base (B)\\n mstore(add(pointer, 0x60), self)\\n // Define the exponent (E)\\n mstore(add(pointer, 0x80), pp1div4)\\n // We save the point of the last argument, it will be override by the result\\n // of the precompile call in order to avoid paying for the memory expansion properly\\n let _result := add(pointer, 0xa0)\\n // Define the modulus (M)\\n mstore(_result, p)\\n\\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\\n if iszero(\\n staticcall(\\n not(0), // amount of gas to send\\n MODEXP_PRECOMPILE, // target\\n pointer, // argsOffset\\n 0xc0, // argsSize (6 * 32 bytes)\\n _result, // retOffset (we override M to avoid paying for the memory expansion)\\n 0x20 // retSize (32 bytes)\\n )\\n ) { revert(0, 0) }\\n\\n result := mload(_result)\\n// result :=addmod(result,0,p)\\n }\\n if(mulmod(result,result,p)!=self){\\n result=_NOTSQUARE;\\n }\\n \\n return result;\\n}\\n /**\\n * /* @dev Convert from affine rep to XYZZ rep\\n */\\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\\n unchecked {\\n P[2] = 1; //ZZ\\n P[3] = 1; //ZZZ\\n P[0] = x0;\\n P[1] = y0;\\n }\\n }\\n\\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \\n\\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\\n\\n y=SqrtMod(y2);\\n if(y==_NOTSQUARE){\\n return _NOTONCURVE;\\n }\\n if((y&1)!=(parity&1)){\\n y=p-y;\\n }\\n }\\n\\n /**\\n * /* @dev Convert from XYZZ rep to affine rep\\n */\\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\\n y1 = mulmod(y, zzzInv, p); //Y/zzz\\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\\n zzzInv = mulmod(_b, _b, p); //1/zz\\n x1 = mulmod(x, zzzInv, p); //X/zz\\n }\\n\\n /**\\n * /* @dev Sutherland2008 doubling\\n */\\n /* The \\\"dbl-2008-s-1\\\" doubling formulas */\\n\\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n assembly {\\n P0 := mulmod(2, y, p) //U = 2*Y1\\n P2 := mulmod(P0, P0, p) // V=U^2\\n P3 := mulmod(x, P2, p) // S = X1*V\\n P1 := mulmod(P0, P2, p) // W=UV\\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\\n }\\n }\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\\n */\\n\\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n if (y1 == 0) {\\n return (x2, y2, 1, 1);\\n }\\n\\n assembly {\\n y1 := sub(p, y1)\\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\\n P0 := mulmod(x2, x2, p) //PP = P^2\\n P1 := mulmod(P0, x2, p) //PPP = P*PP\\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\\n }\\n //end assembly\\n } //end unchecked\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Return the zero curve in XYZZ coordinates.\\n */\\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\\n return (0, 0, 0, 0);\\n }\\n /**\\n * @dev Check if point is the neutral of the curve\\n */\\n\\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\\n return y0 == 0;\\n }\\n /**\\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\\n */\\n\\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\\n return (0, 0);\\n }\\n\\n /**\\n * @dev Check if the curve is the zero curve in affine rep.\\n */\\n // uint256 x, uint256 y)\\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\\n return (y == 0);\\n }\\n\\n /**\\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\\n */\\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\\n return false;\\n }\\n unchecked {\\n uint256 LHS = mulmod(y, y, p); // y^2\\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n\\n return LHS == RHS;\\n }\\n }\\n\\n /**\\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\\n */\\n\\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\\n uint256 zz0;\\n uint256 zzz0;\\n\\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\\n if((x0==x1)&&(y0==y1)) {\\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\\n }\\n else{\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\n }\\n\\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\\n }\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns only x for ECDSA use \\n * */\\n function ecZZ_mulmuladd_S_asm(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 Y;\\n uint256 index = 255;\\n uint256 H0;\\n uint256 H1;\\n\\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n\\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \\n if((H0==0)&&(H1==0))//handling Q=-G\\n {\\n scalar_u=addmod(scalar_u, n-scalar_v, n);\\n scalar_v=0;\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n }\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n X := H0\\n Y := H1\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := H0\\n T2 := H1\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n let T := mload(0x40)\\n mstore(add(T, 0x60), zz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n //Y:=mulmod(Y,zzz,p)//Y/zzz\\n //zz :=mulmod(zz, mload(T),p) //1/z\\n //zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, mload(T), p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return X;\\n }\\n\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns affine representation of point (normalized) \\n * */\\n function ecZZ_mulmuladd(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X, uint256 Y) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 index = 255;\\n uint256[6] memory T;\\n uint256[2] memory H;\\n \\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\\n\\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\\n\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n Y := mload(add(H,32))\\n X := mload(H)\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := mload(H)\\n T2 := mload(add(H,32))\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zzz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n Y:=mulmod(Y,mload(T),p)//Y/zzz\\n zz :=mulmod(zz, mload(T),p) //1/z\\n zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, zz, p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return (X,Y);\\n }\\n\\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\\n //contract at given address dataPointer\\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\\n // the external tool to generate tables from public key is in the /sage directory\\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n unchecked {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n extcodecopy(dataPointer, T, mload(T), 64)\\n let index := sub(zz, 1)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for {} gt(index, 191) { index := add(index, 191) } {\\n //inline Double\\n {\\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(TT1, TT1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n let T1 := mulmod(TT1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n }\\n {\\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n let index2 := sub(index, 64)\\n let T3 :=\\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\\n let index3 := sub(index2, 64)\\n let T2 :=\\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\\n index := sub(index3, 64)\\n let T1 :=\\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T1) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n extcodecopy(dataPointer, T, T1, 64)\\n }\\n\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n\\n // inlined EcZZ_AddN\\n if iszero(zz) {\\n X := mload(T)\\n Y := mload(add(T, 32))\\n zz := 1\\n zzz := 1\\n\\n continue\\n }\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n\\n //special case ecAdd(P,P)=EcDbl\\n if iszero(y2) {\\n if iszero(T2) {\\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n let T4 := mulmod(T2, T2, p)\\n let T1 := mulmod(T4, T2, p) //\\n zz := mulmod(zz, T4, p)\\n //zzz3=V*ZZ1\\n zzz := mulmod(zzz, T1, p) // W=UV/\\n let zz1 := mulmod(X, T4, p)\\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n \\n\\n // improving the extcodecopy trick : append array at end of contract\\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n unchecked {\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n codecopy(T, add(mload(T), dataPointer), 64)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n //index:=add(index,192), restore index, interleaved with loop\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T4) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n codecopy(T, add(T4, dataPointer), 64)\\n\\n // inlined EcZZ_AddN\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n T4 := mulmod(T2, T2, p)\\n T1 := mulmod(T4, T2, p)\\n T2 := mulmod(zz, T4, p) // W=UV\\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\\n let zz1 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\\n zz := T2\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n\\n\\n} //EOF\\n\",\"keccak256\":\"0x7f244805668cc589ae33f18c35c68738db25994c9befbb5d07f28a91fb03ba44\",\"license\":\"MIT\"},\"FreshCryptoLib/utils/Base64Url.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Encode (without '=' padding) \\n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\\n */\\nlibrary Base64Url {\\n /**\\n * @dev Base64Url Encoding Table\\n */\\n string internal constant ENCODING_TABLE =\\n \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\\\";\\n\\n function encode(bytes memory data) internal pure returns (string memory) {\\n if (data.length == 0) return \\\"\\\";\\n\\n // Load the table into memory\\n string memory table = ENCODING_TABLE;\\n\\n string memory result = new string(4 * ((data.length + 2) / 3));\\n\\n // @solidity memory-safe-assembly\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let dataPtr := data\\n let endPtr := add(data, mload(data))\\n } lt(dataPtr, endPtr) {\\n\\n } {\\n dataPtr := add(dataPtr, 3)\\n let input := mload(dataPtr)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n resultPtr := add(resultPtr, 1)\\n }\\n\\n // Remove the padding adjustment logic\\n switch mod(mload(data), 3)\\n case 1 {\\n // Adjust for the last byte of data\\n resultPtr := sub(resultPtr, 2)\\n }\\n case 2 {\\n // Adjust for the last two bytes of data\\n resultPtr := sub(resultPtr, 1)\\n }\\n \\n // Set the correct length of the result string\\n mstore(result, sub(resultPtr, add(result, 32)))\\n }\\n\\n return result; \\n }\\n}\\n\",\"keccak256\":\"0xc9d5fbb0ef9ff0756eb5aabe7a32b2bf0f8f3c533d4451dd5778fe77aee7f0c1\",\"license\":\"Apache-2.0\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title P256Signer\\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This contract is the implementation. It is meant to be used through\\n/// proxy clone.\\ncontract P256Signer {\\n /// @notice The EIP-1271 magic value\\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\\n\\n /// @notice The old EIP-1271 magic value\\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\\n\\n /// @notice Whether the contract has been initialized\\n bool public initialized;\\n\\n /// @notice The x coordinate of the secp256r1 public key\\n uint256 public x;\\n\\n /// @notice The y coordinate of the secp256r1 public key\\n uint256 public y;\\n\\n /// @notice Error message when the signature is invalid\\n error InvalidSignature();\\n\\n /// @notice Error message when the hash is invalid\\n error InvalidHash();\\n\\n /// @notice Error message when the contract is already initialized\\n error AlreadyInitialized();\\n\\n constructor() {\\n initialized = true;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(abi.encode(_hash), _signature);\\n return EIP1271_MAGICVALUE;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @dev This is the old version of the function of EIP-1271 using bytes\\n /// memory instead of bytes32\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\n }\\n\\n struct SignatureLayout {\\n bytes authenticatorData;\\n bytes clientData;\\n uint256 challengeOffset;\\n uint256[2] rs;\\n }\\n\\n /// @notice Validates the signature\\n /// @param data The data signed\\n /// @param _signature The signature\\n function _validate(bytes memory data, bytes calldata _signature) private view {\\n bytes32 _hash = keccak256(data);\\n SignatureLayout calldata signaturePointer;\\n // This code should precalculate the offsets of variables as defined in the layout\\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\\n assembly {\\n signaturePointer := _signature.offset\\n }\\n\\n bool valid = FCL_WebAuthn.checkSignature(\\n signaturePointer.authenticatorData,\\n 0x01,\\n signaturePointer.clientData,\\n _hash,\\n signaturePointer.challengeOffset,\\n signaturePointer.rs,\\n x,\\n y\\n );\\n\\n if (!valid) revert InvalidSignature();\\n }\\n\\n /// @dev This function is only callable once and needs to be called immediately\\n /// after deployment by the factory in the same transaction.\\n /// @param x_ The x coordinate of the public key\\n /// @param y_ The y coordinate of the public key\\n function initialize(uint256 x_, uint256 y_) external {\\n if (initialized) revert AlreadyInitialized();\\n initialized = true;\\n x = x_;\\n y = y_;\\n }\\n}\\n\",\"keccak256\":\"0xfc1b006adb6ace0364918015a1aa64439374f813383bcc71290f6b37b66641e5\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561206a8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cd8565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d53565b61017c565b61008060025481565b61012361011e366004611e3f565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e61565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e61565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ec6565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d24565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ef5565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f53565b67ffffffffffffffff8111156104a7576104a7611d24565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f66565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f76565b90508060208b018301526002826040516105499190611ef5565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f76565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f8f565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611ff560409139905060006003845160026107459190611f53565b61074f9190611fa2565b61075a906004611fdd565b67ffffffffffffffff81111561077257610772611d24565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff831480156108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611580565b909250905081158015610aea575080155b15610b5b577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a0898506000975088158015610b47575087155b15610b5b57600096505050505050506106ef565b600189841c16600189851c1660011b015b80610b8e5760018403935060018a851c1660018a861c1660011b019050610b6c565b50600189841c16600189851c1660011b01955060018603610bf0577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610bff578a96508993505b60038603610c0e578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114d0577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610ef957877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114c5565b60018103610f48577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f57578e93508d92505b60038103610f66578593508492505b89610f7f57509198506001975087965094506114c59050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8809089350806112be57836112be577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114c5565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610c1d565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61154b57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b600080808086611597578585935093505050611605565b846115a9578787935093505050611605565b85881480156115b757508487145b156115d8576115c9888860018061160e565b929a50909850925090506115f2565b6115e788886001808a8a611898565b929a50909850925090505b6115fe88888484611b5d565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b600080600080886000036118b757508492508391506001905080611b50565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b6b84611c12565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611ca157600080fd5b50813567ffffffffffffffff811115611cb957600080fd5b602083019150836020828501011115611cd157600080fd5b9250929050565b600080600060408486031215611ced57600080fd5b83359250602084013567ffffffffffffffff811115611d0b57600080fd5b611d1786828701611c8f565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d6857600080fd5b833567ffffffffffffffff80821115611d8057600080fd5b818601915086601f830112611d9457600080fd5b813581811115611da657611da6611d24565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dec57611dec611d24565b81604052828152896020848701011115611e0557600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e3257600080fd5b50611d1786828701611c8f565b60008060408385031215611e5257600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e9657600080fd5b83018035915067ffffffffffffffff821115611eb157600080fd5b602001915036819003821315611cd157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611f165760208186018101518583015201611efc565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f24565b8183823760009101908152919050565b600060208284031215611f8857600080fd5b5051919050565b818103818111156109da576109da611f24565b600082611fd8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f2456fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa2646970667358221220c618cb60ccea4d134580893ea1be714ea2f3ee81e84f2989f14e663d114ee00a64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cd8565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d53565b61017c565b61008060025481565b61012361011e366004611e3f565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e61565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e61565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ec6565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d24565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ef5565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f53565b67ffffffffffffffff8111156104a7576104a7611d24565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f66565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f76565b90508060208b018301526002826040516105499190611ef5565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f76565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f8f565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611ff560409139905060006003845160026107459190611f53565b61074f9190611fa2565b61075a906004611fdd565b67ffffffffffffffff81111561077257610772611d24565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff831480156108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611580565b909250905081158015610aea575080155b15610b5b577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a0898506000975088158015610b47575087155b15610b5b57600096505050505050506106ef565b600189841c16600189851c1660011b015b80610b8e5760018403935060018a851c1660018a861c1660011b019050610b6c565b50600189841c16600189851c1660011b01955060018603610bf0577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610bff578a96508993505b60038603610c0e578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114d0577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610ef957877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114c5565b60018103610f48577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f57578e93508d92505b60038103610f66578593508492505b89610f7f57509198506001975087965094506114c59050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8809089350806112be57836112be577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114c5565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610c1d565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61154b57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b600080808086611597578585935093505050611605565b846115a9578787935093505050611605565b85881480156115b757508487145b156115d8576115c9888860018061160e565b929a50909850925090506115f2565b6115e788886001808a8a611898565b929a50909850925090505b6115fe88888484611b5d565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b600080600080886000036118b757508492508391506001905080611b50565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b6b84611c12565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611ca157600080fd5b50813567ffffffffffffffff811115611cb957600080fd5b602083019150836020828501011115611cd157600080fd5b9250929050565b600080600060408486031215611ced57600080fd5b83359250602084013567ffffffffffffffff811115611d0b57600080fd5b611d1786828701611c8f565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d6857600080fd5b833567ffffffffffffffff80821115611d8057600080fd5b818601915086601f830112611d9457600080fd5b813581811115611da657611da6611d24565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dec57611dec611d24565b81604052828152896020848701011115611e0557600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e3257600080fd5b50611d1786828701611c8f565b60008060408385031215611e5257600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e9657600080fd5b83018035915067ffffffffffffffff821115611eb157600080fd5b602001915036819003821315611cd157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611f165760208186018101518583015201611efc565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f24565b8183823760009101908152919050565b600060208284031215611f8857600080fd5b5051919050565b818103818111156109da576109da611f24565b600082611fd8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f2456fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa2646970667358221220c618cb60ccea4d134580893ea1be714ea2f3ee81e84f2989f14e663d114ee00a64736f6c63430008140033", + "devdoc": { + "details": "This contract is the implementation. It is meant to be used through proxy clone.", + "kind": "dev", + "methods": { + "initialize(uint256,uint256)": { + "details": "This function is only callable once and needs to be called immediately after deployment by the factory in the same transaction.", + "params": { + "x_": "The x coordinate of the public key", + "y_": "The y coordinate of the public key" + } + }, + "isValidSignature(bytes,bytes)": { + "details": "This is the old version of the function of EIP-1271 using bytes memory instead of bytes32", + "params": { + "_hash": "The hash of the data signed", + "_signature": "The signature" + }, + "returns": { + "_0": "The EIP-1271 magic value" + } + }, + "isValidSignature(bytes32,bytes)": { + "params": { + "_hash": "The hash of the data signed", + "_signature": "The signature" + }, + "returns": { + "_0": "The EIP-1271 magic value" + } + } + }, + "title": "P256Signer", + "version": 1 + }, + "userdoc": { + "errors": { + "AlreadyInitialized()": [ + { + "notice": "Error message when the contract is already initialized" + } + ], + "InvalidHash()": [ + { + "notice": "Error message when the hash is invalid" + } + ], + "InvalidSignature()": [ + { + "notice": "Error message when the signature is invalid" + } + ] + }, + "kind": "user", + "methods": { + "initialized()": { + "notice": "Whether the contract has been initialized" + }, + "isValidSignature(bytes,bytes)": { + "notice": "Verifies that the signer is the owner of the secp256r1 public key." + }, + "isValidSignature(bytes32,bytes)": { + "notice": "Verifies that the signer is the owner of the secp256r1 public key." + }, + "x()": { + "notice": "The x coordinate of the secp256r1 public key" + }, + "y()": { + "notice": "The y coordinate of the secp256r1 public key" + } + }, + "notice": "A contract used to verify ECDSA signatures over secp256r1 through EIP-1271 of Webauthn payloads.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2870, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 2873, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "x", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 2876, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "y", + "offset": 0, + "slot": "2", + "type": "t_uint256" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/arbitrum_production/P256SignerFactory.json b/deployments/arbitrum_production/P256SignerFactory.json new file mode 100644 index 0000000..1b3ce1a --- /dev/null +++ b/deployments/arbitrum_production/P256SignerFactory.json @@ -0,0 +1,137 @@ +{ + "address": "0xa726C1619bB28cc0e1303eFEa80BbAF9FE42389f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "x", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "y", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "NewSignerCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "y", + "type": "uint256" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x836b82d15ee30a601f05742148536dd86c9de481f404d7a14f14adfdac2bee6a", + "receipt": { + "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", + "from": "0x61f2ad863873d2466B64cef9cdC65361F98A65D3", + "contractAddress": null, + "transactionIndex": 2, + "gasUsed": "359217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x94df29de3c94179431e19aae552668e0f60c260bb934a9dee30cfccc3c3d00ce", + "transactionHash": "0x836b82d15ee30a601f05742148536dd86c9de481f404d7a14f14adfdac2bee6a", + "logs": [], + "blockNumber": 194763001, + "cumulativeGasUsed": "568718", + "status": 1, + "byzantium": true + }, + "args": [ + "0x93ae54DAE3A266d2F7197d118e1B3A89429ba55F" + ], + "numDeployments": 1, + "solcInputHash": "01c9a206ce5ca6951fd356b6a1b5a7d7", + "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"NewSignerCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"create(uint256,uint256)\":{\"params\":{\"x\":\"The x coordinate of the public key\",\"y\":\"The y coordinate of the public key\"}}},\"title\":\"P256SignerFactory\",\"version\":1},\"userdoc\":{\"events\":{\"NewSignerCreated(uint256,uint256,address)\":{\"notice\":\"Emitted when a new P256Signer proxy contract is created\"}},\"kind\":\"user\",\"methods\":{\"create(uint256,uint256)\":{\"notice\":\"Creates a new P256Signer proxy contract\"},\"implementation()\":{\"notice\":\"The implementation address of the P256Signer contract\"}},\"notice\":\"Factory contract for creating proxies for P256Signer\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/P256SignerFactory.sol\":\"P256SignerFactory\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"FreshCryptoLib/FCL_Webauthn.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_elliptic.sol\\n///*\\n///*\\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\nimport {FCL_ecdsa} from \\\"./FCL_ecdsa.sol\\\";\\n\\nimport {FCL_ecdsa_utils} from \\\"./FCL_ecdsa_utils.sol\\\";\\n\\nlibrary FCL_WebAuthn {\\n error InvalidAuthenticatorData();\\n error InvalidClientData();\\n error InvalidSignature();\\n\\n function WebAuthn_format(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata // rs\\n ) internal pure returns (bytes32 result) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n {\\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\\n revert InvalidAuthenticatorData();\\n }\\n // Verify that clientData commits to the expected client challenge\\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\\n bytes memory challengeExtracted = new bytes(\\n bytes(challengeEncoded).length\\n );\\n\\n assembly {\\n calldatacopy(\\n add(challengeExtracted, 32),\\n add(clientData.offset, clientChallengeDataOffset),\\n mload(challengeExtracted)\\n )\\n }\\n\\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\\n assembly {\\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\\n }\\n\\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\\n revert InvalidClientData();\\n }\\n } //avoid stack full\\n\\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\\n\\n assembly {\\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\\n }\\n\\n bytes32 more = sha256(clientData);\\n assembly {\\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\\n }\\n\\n return sha256(verifyData);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256[2] calldata Q\\n ) internal view returns (bool) {\\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 Qx,\\n uint256 Qy\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\\n\\n return result;\\n }\\n\\n function checkSignature_prec(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n address dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\\n\\n return result;\\n }\\n\\n //beware that this implementation will not be compliant with EOF\\n function checkSignature_hackmem(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc2811ef6e17ea1d5509a3d3f7d5af5e56583347b36093d05530425d7c1316dd6\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n /**\\n * @dev ECDSA verification, given , signature, and public key, no calldata version\\n */\\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\\n\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n \\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n\\n x1= addmod(x1, n-r,n );\\n \\n return x1 == 0;\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n \\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n}\\n\",\"keccak256\":\"0x679d2e9a655cd7e156a0cfc24de0aca88d4e0b34a8e0dfe6a599f23af092f5a2\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa_utils.sol\":{\"content\":\"\\n//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa_utils {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n x1= addmod(x1, n-r,n );\\n \\n \\n return x1 == 0;\\n }\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\n return ecdsa_verify(message, rs, Q[0], Q[1]);\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n\\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\\n //K is nonce, kpriv is private key\\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\\n {\\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \\n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n //ecdsa key derivation\\n //kpriv is private key return (x,y) coordinates of associated Pubkey\\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\\n {\\n \\n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\\n \\n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\\n {\\n y=FCL_Elliptic_ZZ.p-y;\\n } \\n\\n }\\n \\n //precomputations for 8 dimensional trick\\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\\n {\\n \\n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\\n \\n //the trivial private keys 1 and -1 are forbidden\\n if(Qx==FCL_Elliptic_ZZ.gx)\\n {\\n revert();\\n }\\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\\n \\n Pow64_PQ[4][0]=Qx;\\n Pow64_PQ[4][1]=Qy;\\n \\n /* raise to multiplication by 64 by 6 consecutive doubling*/\\n for(uint j=1;j<4;j++){\\n uint256 x;\\n uint256 y;\\n uint256 zz;\\n uint256 zzz;\\n \\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\\n \\t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\\n \\t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n\\n \\tfor(uint i=0;i<63;i++){\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t}\\n }\\n \\n /* neutral point */\\n Prec[0][0]=0;\\n Prec[0][1]=0;\\n \\n \\t\\n for(uint i=1;i<256;i++)\\n { \\n Prec[i][0]=0;\\n Prec[i][1]=0;\\n \\n for(uint j=0;j<8;j++)\\n {\\n \\tif( (i&(1<=0.8.19 <0.9.0;\\n\\nlibrary FCL_Elliptic_ZZ {\\n // Set parameters for curve sec256r1.\\n\\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\\n //curve prime field modulus\\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n //short weierstrass first coefficient\\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n //short weierstrass second coefficient\\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n //generating point affine coordinates\\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n //curve order (number of points)\\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\\n /* -2 mod n constant, used to speed up inversion*/\\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\\n\\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n //P+1 div 4\\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\\n //arbitrary constant to express no quadratic residuosity\\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n /**\\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\\n */\\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2modn)\\n mstore(add(pointer, 0xa0), n)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n /**\\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\\n */\\n\\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2)\\n mstore(add(pointer, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n\\n //Coron projective shuffling, take as input alpha as blinding factor\\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n \\n uint256 alpha2=mulmod(alpha,alpha,p);\\n \\n x3=mulmod(alpha2, x,p); //alpha^-2.x\\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\\n\\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\\n \\n return (x3, y3, zz3, zzz3);\\n }\\n\\n\\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\\n u2=addmod(u2, p-u1, p);// P = U2-U1\\n x1=mulmod(u2, u2, p);//PP\\n x2=mulmod(x1, u2, p);//PPP\\n \\n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \\n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\\n\\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \\n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\\n\\n return (x3, y3, zz3, zzz3);\\n }\\n\\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\\n/// @param self The integer of which to find the modular inverse\\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\\n\\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\\n assembly (\\\"memory-safe\\\") {\\n // load the free memory pointer value\\n let pointer := mload(0x40)\\n\\n // Define length of base (Bsize)\\n mstore(pointer, 0x20)\\n // Define the exponent size (Esize)\\n mstore(add(pointer, 0x20), 0x20)\\n // Define the modulus size (Msize)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base (B)\\n mstore(add(pointer, 0x60), self)\\n // Define the exponent (E)\\n mstore(add(pointer, 0x80), pp1div4)\\n // We save the point of the last argument, it will be override by the result\\n // of the precompile call in order to avoid paying for the memory expansion properly\\n let _result := add(pointer, 0xa0)\\n // Define the modulus (M)\\n mstore(_result, p)\\n\\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\\n if iszero(\\n staticcall(\\n not(0), // amount of gas to send\\n MODEXP_PRECOMPILE, // target\\n pointer, // argsOffset\\n 0xc0, // argsSize (6 * 32 bytes)\\n _result, // retOffset (we override M to avoid paying for the memory expansion)\\n 0x20 // retSize (32 bytes)\\n )\\n ) { revert(0, 0) }\\n\\n result := mload(_result)\\n// result :=addmod(result,0,p)\\n }\\n if(mulmod(result,result,p)!=self){\\n result=_NOTSQUARE;\\n }\\n \\n return result;\\n}\\n /**\\n * /* @dev Convert from affine rep to XYZZ rep\\n */\\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\\n unchecked {\\n P[2] = 1; //ZZ\\n P[3] = 1; //ZZZ\\n P[0] = x0;\\n P[1] = y0;\\n }\\n }\\n\\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \\n\\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\\n\\n y=SqrtMod(y2);\\n if(y==_NOTSQUARE){\\n return _NOTONCURVE;\\n }\\n if((y&1)!=(parity&1)){\\n y=p-y;\\n }\\n }\\n\\n /**\\n * /* @dev Convert from XYZZ rep to affine rep\\n */\\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\\n y1 = mulmod(y, zzzInv, p); //Y/zzz\\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\\n zzzInv = mulmod(_b, _b, p); //1/zz\\n x1 = mulmod(x, zzzInv, p); //X/zz\\n }\\n\\n /**\\n * /* @dev Sutherland2008 doubling\\n */\\n /* The \\\"dbl-2008-s-1\\\" doubling formulas */\\n\\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n assembly {\\n P0 := mulmod(2, y, p) //U = 2*Y1\\n P2 := mulmod(P0, P0, p) // V=U^2\\n P3 := mulmod(x, P2, p) // S = X1*V\\n P1 := mulmod(P0, P2, p) // W=UV\\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\\n }\\n }\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\\n */\\n\\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n if (y1 == 0) {\\n return (x2, y2, 1, 1);\\n }\\n\\n assembly {\\n y1 := sub(p, y1)\\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\\n P0 := mulmod(x2, x2, p) //PP = P^2\\n P1 := mulmod(P0, x2, p) //PPP = P*PP\\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\\n }\\n //end assembly\\n } //end unchecked\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Return the zero curve in XYZZ coordinates.\\n */\\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\\n return (0, 0, 0, 0);\\n }\\n /**\\n * @dev Check if point is the neutral of the curve\\n */\\n\\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\\n return y0 == 0;\\n }\\n /**\\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\\n */\\n\\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\\n return (0, 0);\\n }\\n\\n /**\\n * @dev Check if the curve is the zero curve in affine rep.\\n */\\n // uint256 x, uint256 y)\\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\\n return (y == 0);\\n }\\n\\n /**\\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\\n */\\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\\n return false;\\n }\\n unchecked {\\n uint256 LHS = mulmod(y, y, p); // y^2\\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n\\n return LHS == RHS;\\n }\\n }\\n\\n /**\\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\\n */\\n\\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\\n uint256 zz0;\\n uint256 zzz0;\\n\\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\\n if((x0==x1)&&(y0==y1)) {\\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\\n }\\n else{\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\n }\\n\\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\\n }\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns only x for ECDSA use \\n * */\\n function ecZZ_mulmuladd_S_asm(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 Y;\\n uint256 index = 255;\\n uint256 H0;\\n uint256 H1;\\n\\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n\\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \\n if((H0==0)&&(H1==0))//handling Q=-G\\n {\\n scalar_u=addmod(scalar_u, n-scalar_v, n);\\n scalar_v=0;\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n }\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n X := H0\\n Y := H1\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := H0\\n T2 := H1\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n let T := mload(0x40)\\n mstore(add(T, 0x60), zz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n //Y:=mulmod(Y,zzz,p)//Y/zzz\\n //zz :=mulmod(zz, mload(T),p) //1/z\\n //zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, mload(T), p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return X;\\n }\\n\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns affine representation of point (normalized) \\n * */\\n function ecZZ_mulmuladd(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X, uint256 Y) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 index = 255;\\n uint256[6] memory T;\\n uint256[2] memory H;\\n \\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\\n\\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\\n\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n Y := mload(add(H,32))\\n X := mload(H)\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := mload(H)\\n T2 := mload(add(H,32))\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zzz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n Y:=mulmod(Y,mload(T),p)//Y/zzz\\n zz :=mulmod(zz, mload(T),p) //1/z\\n zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, zz, p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return (X,Y);\\n }\\n\\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\\n //contract at given address dataPointer\\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\\n // the external tool to generate tables from public key is in the /sage directory\\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n unchecked {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n extcodecopy(dataPointer, T, mload(T), 64)\\n let index := sub(zz, 1)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for {} gt(index, 191) { index := add(index, 191) } {\\n //inline Double\\n {\\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(TT1, TT1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n let T1 := mulmod(TT1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n }\\n {\\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n let index2 := sub(index, 64)\\n let T3 :=\\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\\n let index3 := sub(index2, 64)\\n let T2 :=\\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\\n index := sub(index3, 64)\\n let T1 :=\\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T1) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n extcodecopy(dataPointer, T, T1, 64)\\n }\\n\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n\\n // inlined EcZZ_AddN\\n if iszero(zz) {\\n X := mload(T)\\n Y := mload(add(T, 32))\\n zz := 1\\n zzz := 1\\n\\n continue\\n }\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n\\n //special case ecAdd(P,P)=EcDbl\\n if iszero(y2) {\\n if iszero(T2) {\\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n let T4 := mulmod(T2, T2, p)\\n let T1 := mulmod(T4, T2, p) //\\n zz := mulmod(zz, T4, p)\\n //zzz3=V*ZZ1\\n zzz := mulmod(zzz, T1, p) // W=UV/\\n let zz1 := mulmod(X, T4, p)\\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n \\n\\n // improving the extcodecopy trick : append array at end of contract\\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n unchecked {\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n codecopy(T, add(mload(T), dataPointer), 64)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n //index:=add(index,192), restore index, interleaved with loop\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T4) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n codecopy(T, add(T4, dataPointer), 64)\\n\\n // inlined EcZZ_AddN\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n T4 := mulmod(T2, T2, p)\\n T1 := mulmod(T4, T2, p)\\n T2 := mulmod(zz, T4, p) // W=UV\\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\\n let zz1 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\\n zz := T2\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n\\n\\n} //EOF\\n\",\"keccak256\":\"0x7f244805668cc589ae33f18c35c68738db25994c9befbb5d07f28a91fb03ba44\",\"license\":\"MIT\"},\"FreshCryptoLib/utils/Base64Url.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Encode (without '=' padding) \\n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\\n */\\nlibrary Base64Url {\\n /**\\n * @dev Base64Url Encoding Table\\n */\\n string internal constant ENCODING_TABLE =\\n \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\\\";\\n\\n function encode(bytes memory data) internal pure returns (string memory) {\\n if (data.length == 0) return \\\"\\\";\\n\\n // Load the table into memory\\n string memory table = ENCODING_TABLE;\\n\\n string memory result = new string(4 * ((data.length + 2) / 3));\\n\\n // @solidity memory-safe-assembly\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let dataPtr := data\\n let endPtr := add(data, mload(data))\\n } lt(dataPtr, endPtr) {\\n\\n } {\\n dataPtr := add(dataPtr, 3)\\n let input := mload(dataPtr)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n resultPtr := add(resultPtr, 1)\\n }\\n\\n // Remove the padding adjustment logic\\n switch mod(mload(data), 3)\\n case 1 {\\n // Adjust for the last byte of data\\n resultPtr := sub(resultPtr, 2)\\n }\\n case 2 {\\n // Adjust for the last two bytes of data\\n resultPtr := sub(resultPtr, 1)\\n }\\n \\n // Set the correct length of the result string\\n mstore(result, sub(resultPtr, add(result, 32)))\\n }\\n\\n return result; \\n }\\n}\\n\",\"keccak256\":\"0xc9d5fbb0ef9ff0756eb5aabe7a32b2bf0f8f3c533d4451dd5778fe77aee7f0c1\",\"license\":\"Apache-2.0\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title P256Signer\\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This contract is the implementation. It is meant to be used through\\n/// proxy clone.\\ncontract P256Signer {\\n /// @notice The EIP-1271 magic value\\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\\n\\n /// @notice The old EIP-1271 magic value\\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\\n\\n /// @notice Whether the contract has been initialized\\n bool public initialized;\\n\\n /// @notice The x coordinate of the secp256r1 public key\\n uint256 public x;\\n\\n /// @notice The y coordinate of the secp256r1 public key\\n uint256 public y;\\n\\n /// @notice Error message when the signature is invalid\\n error InvalidSignature();\\n\\n /// @notice Error message when the hash is invalid\\n error InvalidHash();\\n\\n /// @notice Error message when the contract is already initialized\\n error AlreadyInitialized();\\n\\n constructor() {\\n initialized = true;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(abi.encode(_hash), _signature);\\n return EIP1271_MAGICVALUE;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @dev This is the old version of the function of EIP-1271 using bytes\\n /// memory instead of bytes32\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\n }\\n\\n struct SignatureLayout {\\n bytes authenticatorData;\\n bytes clientData;\\n uint256 challengeOffset;\\n uint256[2] rs;\\n }\\n\\n /// @notice Validates the signature\\n /// @param data The data signed\\n /// @param _signature The signature\\n function _validate(bytes memory data, bytes calldata _signature) private view {\\n bytes32 _hash = keccak256(data);\\n SignatureLayout calldata signaturePointer;\\n // This code should precalculate the offsets of variables as defined in the layout\\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\\n assembly {\\n signaturePointer := _signature.offset\\n }\\n\\n bool valid = FCL_WebAuthn.checkSignature(\\n signaturePointer.authenticatorData,\\n 0x01,\\n signaturePointer.clientData,\\n _hash,\\n signaturePointer.challengeOffset,\\n signaturePointer.rs,\\n x,\\n y\\n );\\n\\n if (!valid) revert InvalidSignature();\\n }\\n\\n /// @dev This function is only callable once and needs to be called immediately\\n /// after deployment by the factory in the same transaction.\\n /// @param x_ The x coordinate of the public key\\n /// @param y_ The y coordinate of the public key\\n function initialize(uint256 x_, uint256 y_) external {\\n if (initialized) revert AlreadyInitialized();\\n initialized = true;\\n x = x_;\\n y = y_;\\n }\\n}\\n\",\"keccak256\":\"0xfc1b006adb6ace0364918015a1aa64439374f813383bcc71290f6b37b66641e5\"},\"contracts/P256SignerFactory.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {P256Signer} from \\\"./P256Signer.sol\\\";\\nimport \\\"solady/src/utils/LibClone.sol\\\";\\n\\n/// @title P256SignerFactory\\n/// @notice Factory contract for creating proxies for P256Signer\\ncontract P256SignerFactory {\\n /// @notice The implementation address of the P256Signer contract\\n address public immutable implementation;\\n\\n constructor(address implementation_) {\\n implementation = implementation_;\\n }\\n\\n /// @notice Emitted when a new P256Signer proxy contract is created\\n event NewSignerCreated(uint256 indexed x, uint256 indexed y, address signer);\\n\\n /// @notice Creates a new P256Signer proxy contract\\n /// @param x The x coordinate of the public key\\n /// @param y The y coordinate of the public key\\n function create(uint256 x, uint256 y) external returns (address) {\\n bytes32 salt = keccak256(abi.encodePacked(x, y));\\n address signer = LibClone.cloneDeterministic(implementation, salt);\\n P256Signer(signer).initialize(x, y);\\n emit NewSignerCreated(x, y, signer);\\n return signer;\\n }\\n}\\n\",\"keccak256\":\"0x3bdac08bf7a1c4c1621474b10733f74a9487359212705bbca42ec678aa549a53\"},\"solady/src/utils/LibClone.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Minimal proxy library.\\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)\\n/// @author Minimal proxy by 0age (https://github.com/0age)\\n/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie\\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\\n///\\n/// @dev Minimal proxy:\\n/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,\\n/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,\\n/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.\\n///\\n/// @dev Minimal proxy (PUSH0 variant):\\n/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.\\n/// It is optimized first for minimal runtime gas, then for minimal bytecode.\\n/// The PUSH0 clone functions are intentionally postfixed with a jarring \\\"_PUSH0\\\" as\\n/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.\\n/// Please use with caution.\\n///\\n/// @dev Clones with immutable args (CWIA):\\n/// The implementation of CWIA here implements a `receive()` method that emits the\\n/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,\\n/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards\\n/// composability. The minimal proxy implementation does not offer this feature.\\nlibrary LibClone {\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* CUSTOM ERRORS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Unable to deploy the clone.\\n error DeploymentFailed();\\n\\n /// @dev The salt must start with either the zero address or the caller.\\n error SaltDoesNotStartWithCaller();\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* MINIMAL PROXY OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a clone of `implementation`.\\n function clone(address implementation) internal returns (address instance) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n /**\\n * --------------------------------------------------------------------------+\\n * CREATION (9 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * 60 runSize | PUSH1 runSize | r | |\\n * 3d | RETURNDATASIZE | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * --------------------------------------------------------------------------|\\n * RUNTIME (44 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * |\\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | 0 | |\\n * 3d | RETURNDATASIZE | 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 0 0 | |\\n * |\\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |\\n * 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |\\n * |\\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |\\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |\\n * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |\\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |\\n * |\\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |\\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |\\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |\\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\\n * |\\n * 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |\\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\\n * |\\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * --------------------------------------------------------------------------+\\n */\\n\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n instance := create(0, 0x0c, 0x35)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Deploys a deterministic clone of `implementation` with `salt`.\\n function cloneDeterministic(address implementation, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n instance := create2(0, 0x0c, 0x35, salt)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the clone of `implementation`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash(address implementation) internal pure returns (bytes32 hash) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n hash := keccak256(0x0c, 0x35)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic clone of `implementation`,\\n /// with `salt` by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)\\n internal\\n pure\\n returns (address predicted)\\n {\\n bytes32 hash = initCodeHash(implementation);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a PUSH0 clone of `implementation`.\\n function clone_PUSH0(address implementation) internal returns (address instance) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n /**\\n * --------------------------------------------------------------------------+\\n * CREATION (9 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * 60 runSize | PUSH1 runSize | r | |\\n * 5f | PUSH0 | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 5f | PUSH0 | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * --------------------------------------------------------------------------|\\n * RUNTIME (45 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * |\\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\\n * 5f | PUSH0 | 0 | |\\n * 5f | PUSH0 | 0 0 | |\\n * |\\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 | |\\n * 5f | PUSH0 | 0 cds 0 0 | |\\n * 5f | PUSH0 | 0 0 cds 0 0 | |\\n * 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |\\n * |\\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |\\n * 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |\\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |\\n * 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |\\n * f4 | DELEGATECALL | success | [0..cds): calldata |\\n * |\\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success | [0..cds): calldata |\\n * 5f | PUSH0 | 0 rds success | [0..cds): calldata |\\n * 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |\\n * 3e | RETURNDATACOPY | success | [0..rds): returndata |\\n * |\\n * 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |\\n * 57 | JUMPI | | [0..rds): returndata |\\n * |\\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | | [0..rds): returndata |\\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * --------------------------------------------------------------------------+\\n */\\n\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n instance := create(0, 0x0e, 0x36)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\\n function cloneDeterministic_PUSH0(address implementation, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n instance := create2(0, 0x0e, 0x36, salt)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n hash := keccak256(0x0e, 0x36)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,\\n /// with `salt` by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress_PUSH0(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n bytes32 hash = initCodeHash_PUSH0(implementation);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* CLONES WITH IMMUTABLE ARGS OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a minimal proxy with `implementation`,\\n /// using immutable arguments encoded in `data`.\\n ///\\n /// Note: This implementation of CWIA differs from the original implementation.\\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\\n function clone(address implementation, bytes memory data) internal returns (address instance) {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n // The `creationSize` is `extraLength + 108`\\n // The `runSize` is `creationSize - 10`.\\n\\n /**\\n * ---------------------------------------------------------------------------------------------------+\\n * CREATION (10 bytes) |\\n * ---------------------------------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * ---------------------------------------------------------------------------------------------------|\\n * 61 runSize | PUSH2 runSize | r | |\\n * 3d | RETURNDATASIZE | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * ---------------------------------------------------------------------------------------------------|\\n * RUNTIME (98 bytes + extraLength) |\\n * ---------------------------------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * ---------------------------------------------------------------------------------------------------|\\n * |\\n * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds | |\\n * 60 0x2c | PUSH1 0x2c | 0x2c cds | |\\n * 57 | JUMPI | | |\\n * 34 | CALLVALUE | cv | |\\n * 3d | RETURNDATASIZE | 0 cv | |\\n * 52 | MSTORE | | [0..0x20): callvalue |\\n * 7f sig | PUSH32 0x9e.. | sig | [0..0x20): callvalue |\\n * 59 | MSIZE | 0x20 sig | [0..0x20): callvalue |\\n * 3d | RETURNDATASIZE | 0 0x20 sig | [0..0x20): callvalue |\\n * a1 | LOG1 | | [0..0x20): callvalue |\\n * 00 | STOP | | [0..0x20): callvalue |\\n * 5b | JUMPDEST | | |\\n * |\\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds | |\\n * 3d | RETURNDATASIZE | 0 cds | |\\n * 3d | RETURNDATASIZE | 0 0 cds | |\\n * 37 | CALLDATACOPY | | [0..cds): calldata |\\n * |\\n * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata |\\n * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata |\\n * |\\n * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata |\\n * 60 0x62 | PUSH1 0x62 | 0x62 e e 0 0 0 0 | [0..cds): calldata |\\n * 36 | CALLDATASIZE | cds 0x62 e e 0 0 0 0 | [0..cds): calldata |\\n * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * |\\n * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * |\\n * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\\n * |\\n * 60 0x60 | PUSH1 0x60 | 0x60 success 0 rds | [0..rds): returndata |\\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\\n * |\\n * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * ---------------------------------------------------------------------------------------------------+\\n */\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\\n // The actual EVM limit may be smaller and may change over time.\\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Create the instance.\\n instance := create(0, sub(data, 0x4c), add(extraLength, 0x6c))\\n\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Deploys a deterministic clone of `implementation`,\\n /// using immutable arguments encoded in `data`, with `salt`.\\n ///\\n /// Note: This implementation of CWIA differs from the original implementation.\\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\\n function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\\n // The actual EVM limit may be smaller and may change over time.\\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Create the instance.\\n instance := create2(0, sub(data, 0x4c), add(extraLength, 0x6c), salt)\\n\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the clone of `implementation`\\n /// using immutable arguments encoded in `data`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash(address implementation, bytes memory data)\\n internal\\n pure\\n returns (bytes32 hash)\\n {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.\\n // The actual EVM limit may be smaller and may change over time.\\n returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n sub(data, 0x5a),\\n or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Compute and store the bytecode hash.\\n hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic clone of\\n /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(\\n address implementation,\\n bytes memory data,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n bytes32 hash = initCodeHash(implementation, data);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* OTHER OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Returns the address when a contract with initialization code hash,\\n /// `hash`, is deployed with `salt`, by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)\\n internal\\n pure\\n returns (address predicted)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Compute and store the bytecode hash.\\n mstore8(0x00, 0xff) // Write the prefix.\\n mstore(0x35, hash)\\n mstore(0x01, shl(96, deployer))\\n mstore(0x15, salt)\\n predicted := keccak256(0x00, 0x55)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x35, 0)\\n }\\n }\\n\\n /// @dev Reverts if `salt` does not start with either the zero address or the caller.\\n function checkStartsWithCaller(bytes32 salt) internal view {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // If the salt does not start with the zero address or the caller.\\n if iszero(or(iszero(shr(96, salt)), eq(caller(), shr(96, salt)))) {\\n // Store the function selector of `SaltDoesNotStartWithCaller()`.\\n mstore(0x00, 0x2f634836)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x159b64c65da9e6efe93b8df8c6bb1c7672a7511dcaba414aaa3e447f6d7065e6\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d8b0407d1a28cd9f0ad691ad81667640a0419d8054ee5121c474b80b2ce9bf0064736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d8b0407d1a28cd9f0ad691ad81667640a0419d8054ee5121c474b80b2ce9bf0064736f6c63430008140033", + "devdoc": { + "kind": "dev", + "methods": { + "create(uint256,uint256)": { + "params": { + "x": "The x coordinate of the public key", + "y": "The y coordinate of the public key" + } + } + }, + "title": "P256SignerFactory", + "version": 1 + }, + "userdoc": { + "events": { + "NewSignerCreated(uint256,uint256,address)": { + "notice": "Emitted when a new P256Signer proxy contract is created" + } + }, + "kind": "user", + "methods": { + "create(uint256,uint256)": { + "notice": "Creates a new P256Signer proxy contract" + }, + "implementation()": { + "notice": "The implementation address of the P256Signer contract" + } + }, + "notice": "Factory contract for creating proxies for P256Signer", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrum_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json b/deployments/arbitrum_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json new file mode 100644 index 0000000..2c01ac3 --- /dev/null +++ b/deployments/arbitrum_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json @@ -0,0 +1,57 @@ +{ + "language": "Solidity", + "sources": { + "contracts/P256Signer.sol": { + "content": "pragma solidity ^0.8.0;\n\nimport {FCL_WebAuthn} from \"FreshCryptoLib/FCL_Webauthn.sol\";\n\n/// @title P256Signer\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\n/// EIP-1271 of Webauthn payloads.\n/// @dev This contract is the implementation. It is meant to be used through\n/// proxy clone.\ncontract P256Signer {\n /// @notice The EIP-1271 magic value\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\n\n /// @notice The old EIP-1271 magic value\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\n\n /// @notice Whether the contract has been initialized\n bool public initialized;\n\n /// @notice The x coordinate of the secp256r1 public key\n uint256 public x;\n\n /// @notice The y coordinate of the secp256r1 public key\n uint256 public y;\n\n /// @notice Error message when the signature is invalid\n error InvalidSignature();\n\n /// @notice Error message when the hash is invalid\n error InvalidHash();\n\n /// @notice Error message when the contract is already initialized\n error AlreadyInitialized();\n\n constructor() {\n initialized = true;\n }\n\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\n /// @param _hash The hash of the data signed\n /// @param _signature The signature\n /// @return The EIP-1271 magic value\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\n _validate(abi.encode(_hash), _signature);\n return EIP1271_MAGICVALUE;\n }\n\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\n /// @dev This is the old version of the function of EIP-1271 using bytes\n /// memory instead of bytes32\n /// @param _hash The hash of the data signed\n /// @param _signature The signature\n /// @return The EIP-1271 magic value\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\n _validate(_hash, _signature);\n return OLD_EIP1271_MAGICVALUE;\n }\n\n struct SignatureLayout {\n bytes authenticatorData;\n bytes clientData;\n uint256 challengeOffset;\n uint256[2] rs;\n }\n\n /// @notice Validates the signature\n /// @param data The data signed\n /// @param _signature The signature\n function _validate(bytes memory data, bytes calldata _signature) private view {\n bytes32 _hash = keccak256(data);\n SignatureLayout calldata signaturePointer;\n // This code should precalculate the offsets of variables as defined in the layout\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\n assembly {\n signaturePointer := _signature.offset\n }\n\n bool valid = FCL_WebAuthn.checkSignature(\n signaturePointer.authenticatorData,\n 0x01,\n signaturePointer.clientData,\n _hash,\n signaturePointer.challengeOffset,\n signaturePointer.rs,\n x,\n y\n );\n\n if (!valid) revert InvalidSignature();\n }\n\n /// @dev This function is only callable once and needs to be called immediately\n /// after deployment by the factory in the same transaction.\n /// @param x_ The x coordinate of the public key\n /// @param y_ The y coordinate of the public key\n function initialize(uint256 x_, uint256 y_) external {\n if (initialized) revert AlreadyInitialized();\n initialized = true;\n x = x_;\n y = y_;\n }\n}\n" + }, + "contracts/P256SignerFactory.sol": { + "content": "pragma solidity ^0.8.0;\n\nimport {P256Signer} from \"./P256Signer.sol\";\nimport \"solady/src/utils/LibClone.sol\";\n\n/// @title P256SignerFactory\n/// @notice Factory contract for creating proxies for P256Signer\ncontract P256SignerFactory {\n /// @notice The implementation address of the P256Signer contract\n address public immutable implementation;\n\n constructor(address implementation_) {\n implementation = implementation_;\n }\n\n /// @notice Emitted when a new P256Signer proxy contract is created\n event NewSignerCreated(uint256 indexed x, uint256 indexed y, address signer);\n\n /// @notice Creates a new P256Signer proxy contract\n /// @param x The x coordinate of the public key\n /// @param y The y coordinate of the public key\n function create(uint256 x, uint256 y) external returns (address) {\n bytes32 salt = keccak256(abi.encodePacked(x, y));\n address signer = LibClone.cloneDeterministic(implementation, salt);\n P256Signer(signer).initialize(x, y);\n emit NewSignerCreated(x, y, signer);\n return signer;\n }\n}\n" + }, + "FreshCryptoLib/FCL_ecdsa_utils.sol": { + "content": "\n//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n// |__/|_|\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_ecdsa.sol\n///*\n///*\n///* DESCRIPTION: ecdsa verification implementation\n///*\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\n\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\n\n\n\nlibrary FCL_ecdsa_utils {\n // Set parameters for curve sec256r1.public\n //curve order (number of points)\n uint256 constant n = FCL_Elliptic_ZZ.n;\n \n /**\n * @dev ECDSA verification, given , signature, and public key.\n */\n\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return false;\n }\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\n return false;\n }\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\n uint256 x1;\n\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\n x1= addmod(x1, n-r,n );\n \n \n return x1 == 0;\n }\n\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\n return ecdsa_verify(message, rs, Q[0], Q[1]);\n }\n\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\n {\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return address(0);\n }\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\n\n uint256 Qx;\n uint256 Qy;\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\n\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\n }\n\n\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\n //K is nonce, kpriv is private key\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\n {\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\n\n \n if(r==0||s==0){\n revert();\n }\n\n\n }\n\n //ecdsa key derivation\n //kpriv is private key return (x,y) coordinates of associated Pubkey\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\n {\n \n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\n \n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\n {\n y=FCL_Elliptic_ZZ.p-y;\n } \n\n }\n \n //precomputations for 8 dimensional trick\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\n {\n \n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\n \n //the trivial private keys 1 and -1 are forbidden\n if(Qx==FCL_Elliptic_ZZ.gx)\n {\n revert();\n }\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\n \n Pow64_PQ[4][0]=Qx;\n Pow64_PQ[4][1]=Qy;\n \n /* raise to multiplication by 64 by 6 consecutive doubling*/\n for(uint j=1;j<4;j++){\n uint256 x;\n uint256 y;\n uint256 zz;\n uint256 zzz;\n \n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\n \t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\n \t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n\n \tfor(uint i=0;i<63;i++){\n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n \t}\n }\n \n /* neutral point */\n Prec[0][0]=0;\n Prec[0][1]=0;\n \n \t\n for(uint i=1;i<256;i++)\n { \n Prec[i][0]=0;\n Prec[i][1]=0;\n \n for(uint j=0;j<8;j++)\n {\n \tif( (i&(1<=0.8.19 <0.9.0;\n\n\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\n\n\n\nlibrary FCL_ecdsa {\n // Set parameters for curve sec256r1.public\n //curve order (number of points)\n uint256 constant n = FCL_Elliptic_ZZ.n;\n \n /**\n * @dev ECDSA verification, given , signature, and public key.\n */\n\n /**\n * @dev ECDSA verification, given , signature, and public key, no calldata version\n */\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\n\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return false;\n }\n \n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\n return false;\n }\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\n uint256 x1;\n\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\n\n x1= addmod(x1, n-r,n );\n \n return x1 == 0;\n }\n\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\n {\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return address(0);\n }\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\n\n uint256 Qx;\n uint256 Qy;\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\n\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\n }\n\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\n internal view\n returns (bool)\n {\n \n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 X;\n\n //Shamir 8 dimensions\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\n\n X= addmod(X, n-r,n );\n\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\n internal view\n returns (bool)\n {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 X;\n\n //Shamir 8 dimensions\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\n\n X= addmod(X, n-r,n );\n\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n}\n" + }, + "FreshCryptoLib/FCL_elliptic.sol": { + "content": "//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n// |__/|_|\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_elliptic.sol\n///*\n///*\n///* DESCRIPTION: modified XYZZ system coordinates for EVM elliptic point multiplication\n///* optimization\n///*\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\nlibrary FCL_Elliptic_ZZ {\n // Set parameters for curve sec256r1.\n\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\n //curve prime field modulus\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n //short weierstrass first coefficient\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\n //short weierstrass second coefficient\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\n //generating point affine coordinates\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\n //curve order (number of points)\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\n /* -2 mod n constant, used to speed up inversion*/\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\n\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n //P+1 div 4\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\n //arbitrary constant to express no quadratic residuosity\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n\n /**\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\n */\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\n assembly {\n let pointer := mload(0x40)\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(pointer, 0x20)\n mstore(add(pointer, 0x20), 0x20)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base, exponent and modulus\n mstore(add(pointer, 0x60), u)\n mstore(add(pointer, 0x80), minus_2modn)\n mstore(add(pointer, 0xa0), n)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\n result := mload(pointer)\n }\n }\n /**\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\n */\n\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\n assembly {\n let pointer := mload(0x40)\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(pointer, 0x20)\n mstore(add(pointer, 0x20), 0x20)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base, exponent and modulus\n mstore(add(pointer, 0x60), u)\n mstore(add(pointer, 0x80), minus_2)\n mstore(add(pointer, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\n result := mload(pointer)\n }\n }\n\n //Coron projective shuffling, take as input alpha as blinding factor\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\n {\n \n uint256 alpha2=mulmod(alpha,alpha,p);\n \n x3=mulmod(alpha2, x,p); //alpha^-2.x\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\n\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\n \n return (x3, y3, zz3, zzz3);\n }\n\n\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\n {\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\n u2=addmod(u2, p-u1, p);// P = U2-U1\n x1=mulmod(u2, u2, p);//PP\n x2=mulmod(x1, u2, p);//PPP\n \n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\n\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\n\n return (x3, y3, zz3, zzz3);\n }\n\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\n/// @param self The integer of which to find the modular inverse\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\n\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\n assembly (\"memory-safe\") {\n // load the free memory pointer value\n let pointer := mload(0x40)\n\n // Define length of base (Bsize)\n mstore(pointer, 0x20)\n // Define the exponent size (Esize)\n mstore(add(pointer, 0x20), 0x20)\n // Define the modulus size (Msize)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base (B)\n mstore(add(pointer, 0x60), self)\n // Define the exponent (E)\n mstore(add(pointer, 0x80), pp1div4)\n // We save the point of the last argument, it will be override by the result\n // of the precompile call in order to avoid paying for the memory expansion properly\n let _result := add(pointer, 0xa0)\n // Define the modulus (M)\n mstore(_result, p)\n\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\n if iszero(\n staticcall(\n not(0), // amount of gas to send\n MODEXP_PRECOMPILE, // target\n pointer, // argsOffset\n 0xc0, // argsSize (6 * 32 bytes)\n _result, // retOffset (we override M to avoid paying for the memory expansion)\n 0x20 // retSize (32 bytes)\n )\n ) { revert(0, 0) }\n\n result := mload(_result)\n// result :=addmod(result,0,p)\n }\n if(mulmod(result,result,p)!=self){\n result=_NOTSQUARE;\n }\n \n return result;\n}\n /**\n * /* @dev Convert from affine rep to XYZZ rep\n */\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\n unchecked {\n P[2] = 1; //ZZ\n P[3] = 1; //ZZZ\n P[0] = x0;\n P[1] = y0;\n }\n }\n\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \n\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\n\n y=SqrtMod(y2);\n if(y==_NOTSQUARE){\n return _NOTONCURVE;\n }\n if((y&1)!=(parity&1)){\n y=p-y;\n }\n }\n\n /**\n * /* @dev Convert from XYZZ rep to affine rep\n */\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\n y1 = mulmod(y, zzzInv, p); //Y/zzz\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\n zzzInv = mulmod(_b, _b, p); //1/zz\n x1 = mulmod(x, zzzInv, p); //X/zz\n }\n\n /**\n * /* @dev Sutherland2008 doubling\n */\n /* The \"dbl-2008-s-1\" doubling formulas */\n\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\n internal\n pure\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\n {\n unchecked {\n assembly {\n P0 := mulmod(2, y, p) //U = 2*Y1\n P2 := mulmod(P0, P0, p) // V=U^2\n P3 := mulmod(x, P2, p) // S = X1*V\n P1 := mulmod(P0, P2, p) // W=UV\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\n }\n }\n return (P0, P1, P2, P3);\n }\n\n /**\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\n */\n\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\n internal\n pure\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\n {\n unchecked {\n if (y1 == 0) {\n return (x2, y2, 1, 1);\n }\n\n assembly {\n y1 := sub(p, y1)\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\n P0 := mulmod(x2, x2, p) //PP = P^2\n P1 := mulmod(P0, x2, p) //PPP = P*PP\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\n }\n //end assembly\n } //end unchecked\n return (P0, P1, P2, P3);\n }\n\n /**\n * @dev Return the zero curve in XYZZ coordinates.\n */\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\n return (0, 0, 0, 0);\n }\n /**\n * @dev Check if point is the neutral of the curve\n */\n\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\n return y0 == 0;\n }\n /**\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\n */\n\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\n return (0, 0);\n }\n\n /**\n * @dev Check if the curve is the zero curve in affine rep.\n */\n // uint256 x, uint256 y)\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\n return (y == 0);\n }\n\n /**\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\n */\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\n return false;\n }\n unchecked {\n uint256 LHS = mulmod(y, y, p); // y^2\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\n\n return LHS == RHS;\n }\n }\n\n /**\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\n */\n\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\n uint256 zz0;\n uint256 zzz0;\n\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\n if((x0==x1)&&(y0==y1)) {\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\n }\n else{\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\n }\n\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\n }\n\n /**\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\n * Returns only x for ECDSA use \n * */\n function ecZZ_mulmuladd_S_asm(\n uint256 Q0,\n uint256 Q1, //affine rep for input point Q\n uint256 scalar_u,\n uint256 scalar_v\n ) internal view returns (uint256 X) {\n uint256 zz;\n uint256 zzz;\n uint256 Y;\n uint256 index = 255;\n uint256 H0;\n uint256 H1;\n\n unchecked {\n if (scalar_u == 0 && scalar_v == 0) return 0;\n\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \n if((H0==0)&&(H1==0))//handling Q=-G\n {\n scalar_u=addmod(scalar_u, n-scalar_v, n);\n scalar_v=0;\n if (scalar_u == 0 && scalar_v == 0) return 0;\n }\n assembly {\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\n index := sub(index, 1)\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n } {}\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if eq(zz, 1) {\n X := gx\n Y := gy\n }\n if eq(zz, 2) {\n X := Q0\n Y := Q1\n }\n if eq(zz, 3) {\n X := H0\n Y := H1\n }\n\n index := sub(index, 1)\n zz := 1\n zzz := 1\n\n for {} gt(minus_1, index) { index := sub(index, 1) } {\n // inlined EcZZ_Dbl\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n {\n //value of dibit\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if iszero(T4) {\n Y := sub(p, Y) //restore the -Y inversion\n continue\n } // if T4!=0\n\n if eq(T4, 1) {\n T1 := gx\n T2 := gy\n }\n if eq(T4, 2) {\n T1 := Q0\n T2 := Q1\n }\n if eq(T4, 3) {\n T1 := H0\n T2 := H1\n }\n if iszero(zz) {\n X := T1\n Y := T2\n zz := 1\n zzz := 1\n continue\n }\n // inlined EcZZ_AddN\n\n //T3:=sub(p, Y)\n //T3:=Y\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\n\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\n //todo : construct edge vector case\n if iszero(y2) {\n if iszero(T2) {\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n T4 := mulmod(T2, T2, p) //PP\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\n zz := mulmod(zz, T4, p)\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\n let TT2 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\n\n X := T4\n }\n } //end loop\n let T := mload(0x40)\n mstore(add(T, 0x60), zz)\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n //Y:=mulmod(Y,zzz,p)//Y/zzz\n //zz :=mulmod(zz, mload(T),p) //1/z\n //zz:= mulmod(zz,zz,p) //1/zz\n X := mulmod(X, mload(T), p) //X/zz\n } //end assembly\n } //end unchecked\n\n return X;\n }\n\n\n /**\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\n * Returns affine representation of point (normalized) \n * */\n function ecZZ_mulmuladd(\n uint256 Q0,\n uint256 Q1, //affine rep for input point Q\n uint256 scalar_u,\n uint256 scalar_v\n ) internal view returns (uint256 X, uint256 Y) {\n uint256 zz;\n uint256 zzz;\n uint256 index = 255;\n uint256[6] memory T;\n uint256[2] memory H;\n \n unchecked {\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\n\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\n\n assembly {\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\n index := sub(index, 1)\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n } {}\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if eq(zz, 1) {\n X := gx\n Y := gy\n }\n if eq(zz, 2) {\n X := Q0\n Y := Q1\n }\n if eq(zz, 3) {\n Y := mload(add(H,32))\n X := mload(H)\n }\n\n index := sub(index, 1)\n zz := 1\n zzz := 1\n\n for {} gt(minus_1, index) { index := sub(index, 1) } {\n // inlined EcZZ_Dbl\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n {\n //value of dibit\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if iszero(T4) {\n Y := sub(p, Y) //restore the -Y inversion\n continue\n } // if T4!=0\n\n if eq(T4, 1) {\n T1 := gx\n T2 := gy\n }\n if eq(T4, 2) {\n T1 := Q0\n T2 := Q1\n }\n if eq(T4, 3) {\n T1 := mload(H)\n T2 := mload(add(H,32))\n }\n if iszero(zz) {\n X := T1\n Y := T2\n zz := 1\n zzz := 1\n continue\n }\n // inlined EcZZ_AddN\n\n //T3:=sub(p, Y)\n //T3:=Y\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\n\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\n //todo : construct edge vector case\n if iszero(y2) {\n if iszero(T2) {\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n T4 := mulmod(T2, T2, p) //PP\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\n zz := mulmod(zz, T4, p)\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\n let TT2 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\n\n X := T4\n }\n } //end loop\n mstore(add(T, 0x60), zzz)\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n Y:=mulmod(Y,mload(T),p)//Y/zzz\n zz :=mulmod(zz, mload(T),p) //1/z\n zz:= mulmod(zz,zz,p) //1/zz\n X := mulmod(X, zz, p) //X/zz\n } //end assembly\n } //end unchecked\n\n return (X,Y);\n }\n\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\n //contract at given address dataPointer\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\n // the external tool to generate tables from public key is in the /sage directory\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\n internal view\n returns (uint256 X /*, uint Y*/ )\n {\n unchecked {\n uint256 zz; // third and coordinates of the point\n\n uint256[6] memory T;\n zz = 256; //start index\n\n while (T[0] == 0) {\n zz = zz - 1;\n //tbd case of msb octobit is null\n T[0] = 64\n * (\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\n );\n }\n assembly {\n extcodecopy(dataPointer, T, mload(T), 64)\n let index := sub(zz, 1)\n X := mload(T)\n let Y := mload(add(T, 32))\n let zzz := 1\n zz := 1\n\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\n for {} gt(index, 191) { index := add(index, 191) } {\n //inline Double\n {\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(TT1, TT1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n let T1 := mulmod(TT1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n /* compute element to access in precomputed table */\n }\n {\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\n let index2 := sub(index, 64)\n let T3 :=\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\n let index3 := sub(index2, 64)\n let T2 :=\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\n index := sub(index3, 64)\n let T1 :=\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\n\n //tbd: check validity of formulae with (0,1) to remove conditional jump\n if iszero(T1) {\n Y := sub(p, Y)\n\n continue\n }\n extcodecopy(dataPointer, T, T1, 64)\n }\n\n {\n /* Access to precomputed table using extcodecopy hack */\n\n // inlined EcZZ_AddN\n if iszero(zz) {\n X := mload(T)\n Y := mload(add(T, 32))\n zz := 1\n zzz := 1\n\n continue\n }\n\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\n\n //special case ecAdd(P,P)=EcDbl\n if iszero(y2) {\n if iszero(T2) {\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n let T4 := mulmod(T2, T2, p)\n let T1 := mulmod(T4, T2, p) //\n zz := mulmod(zz, T4, p)\n //zzz3=V*ZZ1\n zzz := mulmod(zzz, T1, p) // W=UV/\n let zz1 := mulmod(X, T4, p)\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\n }\n } //end loop\n mstore(add(T, 0x60), zz)\n\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n zz := mload(T)\n X := mulmod(X, zz, p) //X/zz\n }\n } //end unchecked\n }\n\n \n\n // improving the extcodecopy trick : append array at end of contract\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\n internal view\n returns (uint256 X /*, uint Y*/ )\n {\n uint256 zz; // third and coordinates of the point\n\n uint256[6] memory T;\n zz = 256; //start index\n\n unchecked {\n while (T[0] == 0) {\n zz = zz - 1;\n //tbd case of msb octobit is null\n T[0] = 64\n * (\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\n );\n }\n assembly {\n codecopy(T, add(mload(T), dataPointer), 64)\n X := mload(T)\n let Y := mload(add(T, 32))\n let zzz := 1\n zz := 1\n\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n /* compute element to access in precomputed table */\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\n index := sub(index, 64)\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\n index := sub(index, 64)\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\n index := sub(index, 64)\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\n //index:=add(index,192), restore index, interleaved with loop\n\n //tbd: check validity of formulae with (0,1) to remove conditional jump\n if iszero(T4) {\n Y := sub(p, Y)\n\n continue\n }\n {\n /* Access to precomputed table using extcodecopy hack */\n codecopy(T, add(T4, dataPointer), 64)\n\n // inlined EcZZ_AddN\n\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\n T4 := mulmod(T2, T2, p)\n T1 := mulmod(T4, T2, p)\n T2 := mulmod(zz, T4, p) // W=UV\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\n let zz1 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\n zz := T2\n X := T4\n }\n } //end loop\n mstore(add(T, 0x60), zz)\n\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n zz := mload(T)\n X := mulmod(X, zz, p) //X/zz\n }\n } //end unchecked\n }\n\n\n /**\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\n * generation of contract bytecode for precomputations is done using sagemath code\n * (see sage directory, WebAuthn_precompute.sage)\n */\n\n /**\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\n * generation of contract bytecode for precomputations is done using sagemath code\n * (see sage directory, WebAuthn_precompute.sage)\n */\n\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\n internal view\n returns (bool)\n {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via bytecode assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_nModInv(s);\n uint256 X;\n\n //Shamir 8 dimensions\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\n\n assembly {\n X := addmod(X, sub(n, r), n)\n }\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n\n\n} //EOF\n" + }, + "FreshCryptoLib/FCL_Webauthn.sol": { + "content": "//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_elliptic.sol\n///*\n///*\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\nimport {Base64Url} from \"./utils/Base64Url.sol\";\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\nimport {FCL_ecdsa} from \"./FCL_ecdsa.sol\";\n\nimport {FCL_ecdsa_utils} from \"./FCL_ecdsa_utils.sol\";\n\nlibrary FCL_WebAuthn {\n error InvalidAuthenticatorData();\n error InvalidClientData();\n error InvalidSignature();\n\n function WebAuthn_format(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata // rs\n ) internal pure returns (bytes32 result) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n {\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\n revert InvalidAuthenticatorData();\n }\n // Verify that clientData commits to the expected client challenge\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\n bytes memory challengeExtracted = new bytes(\n bytes(challengeEncoded).length\n );\n\n assembly {\n calldatacopy(\n add(challengeExtracted, 32),\n add(clientData.offset, clientChallengeDataOffset),\n mload(challengeExtracted)\n )\n }\n\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\n assembly {\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\n }\n\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\n revert InvalidClientData();\n }\n } //avoid stack full\n\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\n\n assembly {\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\n }\n\n bytes32 more = sha256(clientData);\n assembly {\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\n }\n\n return sha256(verifyData);\n }\n\n function checkSignature (\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256[2] calldata Q\n ) internal view returns (bool) {\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\n }\n\n function checkSignature (\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256 Qx,\n uint256 Qy\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\n\n return result;\n }\n\n function checkSignature_prec(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n address dataPointer\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\n\n return result;\n }\n\n //beware that this implementation will not be compliant with EOF\n function checkSignature_hackmem(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256 dataPointer\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\n\n return result;\n }\n}\n" + }, + "FreshCryptoLib/utils/Base64Url.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\n/**\n * @dev Encode (without '=' padding) \n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\n */\nlibrary Base64Url {\n /**\n * @dev Base64Url Encoding Table\n */\n string internal constant ENCODING_TABLE =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\n function encode(bytes memory data) internal pure returns (string memory) {\n if (data.length == 0) return \"\";\n\n // Load the table into memory\n string memory table = ENCODING_TABLE;\n\n string memory result = new string(4 * ((data.length + 2) / 3));\n\n // @solidity memory-safe-assembly\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let dataPtr := data\n let endPtr := add(data, mload(data))\n } lt(dataPtr, endPtr) {\n\n } {\n dataPtr := add(dataPtr, 3)\n let input := mload(dataPtr)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n resultPtr := add(resultPtr, 1)\n }\n\n // Remove the padding adjustment logic\n switch mod(mload(data), 3)\n case 1 {\n // Adjust for the last byte of data\n resultPtr := sub(resultPtr, 2)\n }\n case 2 {\n // Adjust for the last two bytes of data\n resultPtr := sub(resultPtr, 1)\n }\n \n // Set the correct length of the result string\n mstore(result, sub(resultPtr, add(result, 32)))\n }\n\n return result; \n }\n}\n" + }, + "solady/src/utils/LibClone.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Minimal proxy library.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)\n/// @author Minimal proxy by 0age (https://github.com/0age)\n/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\n///\n/// @dev Minimal proxy:\n/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,\n/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,\n/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.\n///\n/// @dev Minimal proxy (PUSH0 variant):\n/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.\n/// It is optimized first for minimal runtime gas, then for minimal bytecode.\n/// The PUSH0 clone functions are intentionally postfixed with a jarring \"_PUSH0\" as\n/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.\n/// Please use with caution.\n///\n/// @dev Clones with immutable args (CWIA):\n/// The implementation of CWIA here implements a `receive()` method that emits the\n/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,\n/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards\n/// composability. The minimal proxy implementation does not offer this feature.\nlibrary LibClone {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Unable to deploy the clone.\n error DeploymentFailed();\n\n /// @dev The salt must start with either the zero address or the caller.\n error SaltDoesNotStartWithCaller();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MINIMAL PROXY OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a clone of `implementation`.\n function clone(address implementation) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * --------------------------------------------------------------------------+\n * CREATION (9 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * --------------------------------------------------------------------------|\n * RUNTIME (44 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * |\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | |\n * 3d | RETURNDATASIZE | 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 0 0 | |\n * |\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |\n * 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |\n * |\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\n * |\n * 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\n * |\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * --------------------------------------------------------------------------+\n */\n\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n instance := create(0, 0x0c, 0x35)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation` with `salt`.\n function cloneDeterministic(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n instance := create2(0, 0x0c, 0x35, salt)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Returns the initialization code hash of the clone of `implementation`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n hash := keccak256(0x0c, 0x35)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Returns the address of the deterministic clone of `implementation`,\n /// with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)\n internal\n pure\n returns (address predicted)\n {\n bytes32 hash = initCodeHash(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a PUSH0 clone of `implementation`.\n function clone_PUSH0(address implementation) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * --------------------------------------------------------------------------+\n * CREATION (9 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 5f | PUSH0 | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 5f | PUSH0 | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * --------------------------------------------------------------------------|\n * RUNTIME (45 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * |\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n * 5f | PUSH0 | 0 | |\n * 5f | PUSH0 | 0 0 | |\n * |\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 | |\n * 5f | PUSH0 | 0 cds 0 0 | |\n * 5f | PUSH0 | 0 0 cds 0 0 | |\n * 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |\n * 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success | [0..cds): calldata |\n * |\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success | [0..cds): calldata |\n * 5f | PUSH0 | 0 rds success | [0..cds): calldata |\n * 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success | [0..rds): returndata |\n * |\n * 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |\n * 57 | JUMPI | | [0..rds): returndata |\n * |\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | [0..rds): returndata |\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * --------------------------------------------------------------------------+\n */\n\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n instance := create(0, 0x0e, 0x36)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\n function cloneDeterministic_PUSH0(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n instance := create2(0, 0x0e, 0x36, salt)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n hash := keccak256(0x0e, 0x36)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,\n /// with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress_PUSH0(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHash_PUSH0(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CLONES WITH IMMUTABLE ARGS OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a minimal proxy with `implementation`,\n /// using immutable arguments encoded in `data`.\n ///\n /// Note: This implementation of CWIA differs from the original implementation.\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\n function clone(address implementation, bytes memory data) internal returns (address instance) {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n // The `creationSize` is `extraLength + 108`\n // The `runSize` is `creationSize - 10`.\n\n /**\n * ---------------------------------------------------------------------------------------------------+\n * CREATION (10 bytes) |\n * ---------------------------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------------------------|\n * 61 runSize | PUSH2 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * ---------------------------------------------------------------------------------------------------|\n * RUNTIME (98 bytes + extraLength) |\n * ---------------------------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------------------------|\n * |\n * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 60 0x2c | PUSH1 0x2c | 0x2c cds | |\n * 57 | JUMPI | | |\n * 34 | CALLVALUE | cv | |\n * 3d | RETURNDATASIZE | 0 cv | |\n * 52 | MSTORE | | [0..0x20): callvalue |\n * 7f sig | PUSH32 0x9e.. | sig | [0..0x20): callvalue |\n * 59 | MSIZE | 0x20 sig | [0..0x20): callvalue |\n * 3d | RETURNDATASIZE | 0 0x20 sig | [0..0x20): callvalue |\n * a1 | LOG1 | | [0..0x20): callvalue |\n * 00 | STOP | | [0..0x20): callvalue |\n * 5b | JUMPDEST | | |\n * |\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 3d | RETURNDATASIZE | 0 cds | |\n * 3d | RETURNDATASIZE | 0 0 cds | |\n * 37 | CALLDATACOPY | | [0..cds): calldata |\n * |\n * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata |\n * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata |\n * |\n * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata |\n * 60 0x62 | PUSH1 0x62 | 0x62 e e 0 0 0 0 | [0..cds): calldata |\n * 36 | CALLDATASIZE | cds 0x62 e e 0 0 0 0 | [0..cds): calldata |\n * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * |\n * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * |\n * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\n * |\n * 60 0x60 | PUSH1 0x60 | 0x60 success 0 rds | [0..rds): returndata |\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\n * |\n * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * ---------------------------------------------------------------------------------------------------+\n */\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\n // The actual EVM limit may be smaller and may change over time.\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Create the instance.\n instance := create(0, sub(data, 0x4c), add(extraLength, 0x6c))\n\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation`,\n /// using immutable arguments encoded in `data`, with `salt`.\n ///\n /// Note: This implementation of CWIA differs from the original implementation.\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\n function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)\n internal\n returns (address instance)\n {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\n // The actual EVM limit may be smaller and may change over time.\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Create the instance.\n instance := create2(0, sub(data, 0x4c), add(extraLength, 0x6c), salt)\n\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Returns the initialization code hash of the clone of `implementation`\n /// using immutable arguments encoded in `data`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash(address implementation, bytes memory data)\n internal\n pure\n returns (bytes32 hash)\n {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.\n // The actual EVM limit may be smaller and may change over time.\n returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n sub(data, 0x5a),\n or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Compute and store the bytecode hash.\n hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Returns the address of the deterministic clone of\n /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(\n address implementation,\n bytes memory data,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHash(implementation, data);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* OTHER OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns the address when a contract with initialization code hash,\n /// `hash`, is deployed with `salt`, by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)\n internal\n pure\n returns (address predicted)\n {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, hash)\n mstore(0x01, shl(96, deployer))\n mstore(0x15, salt)\n predicted := keccak256(0x00, 0x55)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x35, 0)\n }\n }\n\n /// @dev Reverts if `salt` does not start with either the zero address or the caller.\n function checkStartsWithCaller(bytes32 salt) internal view {\n /// @solidity memory-safe-assembly\n assembly {\n // If the salt does not start with the zero address or the caller.\n if iszero(or(iszero(shr(96, salt)), eq(caller(), shr(96, salt)))) {\n // Store the function selector of `SaltDoesNotStartWithCaller()`.\n mstore(0x00, 0x2f634836)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n }\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/base_production/.chainId b/deployments/base_production/.chainId new file mode 100644 index 0000000..2a0c263 --- /dev/null +++ b/deployments/base_production/.chainId @@ -0,0 +1 @@ +8453 \ No newline at end of file diff --git a/deployments/base_production/P256Signer.json b/deployments/base_production/P256Signer.json new file mode 100644 index 0000000..b7921ef --- /dev/null +++ b/deployments/base_production/P256Signer.json @@ -0,0 +1,275 @@ +{ + "address": "0x93ae54DAE3A266d2F7197d118e1B3A89429ba55F", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHash", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "y_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "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": [ + { + "internalType": "bytes", + "name": "_hash", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "x", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "y", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xde9b000f279594647b1f8988de66da8c26869bea0211463b9c08cbaa936b97b1", + "receipt": { + "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", + "from": "0x61f2ad863873d2466B64cef9cdC65361F98A65D3", + "contractAddress": null, + "transactionIndex": 22, + "gasUsed": "1848511", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5083bcdd40cb26e05b473bcc9b94b8efffcdce4b4c1e92a5335e8ca2f5a264dc", + "transactionHash": "0xde9b000f279594647b1f8988de66da8c26869bea0211463b9c08cbaa936b97b1", + "logs": [], + "blockNumber": 12378999, + "cumulativeGasUsed": "4651439", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "01c9a206ce5ca6951fd356b6a1b5a7d7", + "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAuthenticatorData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidClientData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidHash\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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\":[{\"internalType\":\"bytes\",\"name\":\"_hash\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"isValidSignature\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"y\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract is the implementation. It is meant to be used through proxy clone.\",\"kind\":\"dev\",\"methods\":{\"initialize(uint256,uint256)\":{\"details\":\"This function is only callable once and needs to be called immediately after deployment by the factory in the same transaction.\",\"params\":{\"x_\":\"The x coordinate of the public key\",\"y_\":\"The y coordinate of the public key\"}},\"isValidSignature(bytes,bytes)\":{\"details\":\"This is the old version of the function of EIP-1271 using bytes memory instead of bytes32\",\"params\":{\"_hash\":\"The hash of the data signed\",\"_signature\":\"The signature\"},\"returns\":{\"_0\":\"The EIP-1271 magic value\"}},\"isValidSignature(bytes32,bytes)\":{\"params\":{\"_hash\":\"The hash of the data signed\",\"_signature\":\"The signature\"},\"returns\":{\"_0\":\"The EIP-1271 magic value\"}}},\"title\":\"P256Signer\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInitialized()\":[{\"notice\":\"Error message when the contract is already initialized\"}],\"InvalidHash()\":[{\"notice\":\"Error message when the hash is invalid\"}],\"InvalidSignature()\":[{\"notice\":\"Error message when the signature is invalid\"}]},\"kind\":\"user\",\"methods\":{\"initialized()\":{\"notice\":\"Whether the contract has been initialized\"},\"isValidSignature(bytes,bytes)\":{\"notice\":\"Verifies that the signer is the owner of the secp256r1 public key.\"},\"isValidSignature(bytes32,bytes)\":{\"notice\":\"Verifies that the signer is the owner of the secp256r1 public key.\"},\"x()\":{\"notice\":\"The x coordinate of the secp256r1 public key\"},\"y()\":{\"notice\":\"The y coordinate of the secp256r1 public key\"}},\"notice\":\"A contract used to verify ECDSA signatures over secp256r1 through EIP-1271 of Webauthn payloads.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/P256Signer.sol\":\"P256Signer\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"FreshCryptoLib/FCL_Webauthn.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_elliptic.sol\\n///*\\n///*\\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\nimport {FCL_ecdsa} from \\\"./FCL_ecdsa.sol\\\";\\n\\nimport {FCL_ecdsa_utils} from \\\"./FCL_ecdsa_utils.sol\\\";\\n\\nlibrary FCL_WebAuthn {\\n error InvalidAuthenticatorData();\\n error InvalidClientData();\\n error InvalidSignature();\\n\\n function WebAuthn_format(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata // rs\\n ) internal pure returns (bytes32 result) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n {\\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\\n revert InvalidAuthenticatorData();\\n }\\n // Verify that clientData commits to the expected client challenge\\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\\n bytes memory challengeExtracted = new bytes(\\n bytes(challengeEncoded).length\\n );\\n\\n assembly {\\n calldatacopy(\\n add(challengeExtracted, 32),\\n add(clientData.offset, clientChallengeDataOffset),\\n mload(challengeExtracted)\\n )\\n }\\n\\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\\n assembly {\\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\\n }\\n\\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\\n revert InvalidClientData();\\n }\\n } //avoid stack full\\n\\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\\n\\n assembly {\\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\\n }\\n\\n bytes32 more = sha256(clientData);\\n assembly {\\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\\n }\\n\\n return sha256(verifyData);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256[2] calldata Q\\n ) internal view returns (bool) {\\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 Qx,\\n uint256 Qy\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\\n\\n return result;\\n }\\n\\n function checkSignature_prec(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n address dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\\n\\n return result;\\n }\\n\\n //beware that this implementation will not be compliant with EOF\\n function checkSignature_hackmem(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc2811ef6e17ea1d5509a3d3f7d5af5e56583347b36093d05530425d7c1316dd6\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n /**\\n * @dev ECDSA verification, given , signature, and public key, no calldata version\\n */\\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\\n\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n \\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n\\n x1= addmod(x1, n-r,n );\\n \\n return x1 == 0;\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n \\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n}\\n\",\"keccak256\":\"0x679d2e9a655cd7e156a0cfc24de0aca88d4e0b34a8e0dfe6a599f23af092f5a2\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa_utils.sol\":{\"content\":\"\\n//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa_utils {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n x1= addmod(x1, n-r,n );\\n \\n \\n return x1 == 0;\\n }\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\n return ecdsa_verify(message, rs, Q[0], Q[1]);\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n\\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\\n //K is nonce, kpriv is private key\\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\\n {\\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \\n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n //ecdsa key derivation\\n //kpriv is private key return (x,y) coordinates of associated Pubkey\\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\\n {\\n \\n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\\n \\n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\\n {\\n y=FCL_Elliptic_ZZ.p-y;\\n } \\n\\n }\\n \\n //precomputations for 8 dimensional trick\\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\\n {\\n \\n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\\n \\n //the trivial private keys 1 and -1 are forbidden\\n if(Qx==FCL_Elliptic_ZZ.gx)\\n {\\n revert();\\n }\\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\\n \\n Pow64_PQ[4][0]=Qx;\\n Pow64_PQ[4][1]=Qy;\\n \\n /* raise to multiplication by 64 by 6 consecutive doubling*/\\n for(uint j=1;j<4;j++){\\n uint256 x;\\n uint256 y;\\n uint256 zz;\\n uint256 zzz;\\n \\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\\n \\t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\\n \\t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n\\n \\tfor(uint i=0;i<63;i++){\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t}\\n }\\n \\n /* neutral point */\\n Prec[0][0]=0;\\n Prec[0][1]=0;\\n \\n \\t\\n for(uint i=1;i<256;i++)\\n { \\n Prec[i][0]=0;\\n Prec[i][1]=0;\\n \\n for(uint j=0;j<8;j++)\\n {\\n \\tif( (i&(1<=0.8.19 <0.9.0;\\n\\nlibrary FCL_Elliptic_ZZ {\\n // Set parameters for curve sec256r1.\\n\\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\\n //curve prime field modulus\\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n //short weierstrass first coefficient\\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n //short weierstrass second coefficient\\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n //generating point affine coordinates\\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n //curve order (number of points)\\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\\n /* -2 mod n constant, used to speed up inversion*/\\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\\n\\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n //P+1 div 4\\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\\n //arbitrary constant to express no quadratic residuosity\\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n /**\\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\\n */\\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2modn)\\n mstore(add(pointer, 0xa0), n)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n /**\\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\\n */\\n\\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2)\\n mstore(add(pointer, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n\\n //Coron projective shuffling, take as input alpha as blinding factor\\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n \\n uint256 alpha2=mulmod(alpha,alpha,p);\\n \\n x3=mulmod(alpha2, x,p); //alpha^-2.x\\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\\n\\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\\n \\n return (x3, y3, zz3, zzz3);\\n }\\n\\n\\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\\n u2=addmod(u2, p-u1, p);// P = U2-U1\\n x1=mulmod(u2, u2, p);//PP\\n x2=mulmod(x1, u2, p);//PPP\\n \\n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \\n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\\n\\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \\n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\\n\\n return (x3, y3, zz3, zzz3);\\n }\\n\\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\\n/// @param self The integer of which to find the modular inverse\\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\\n\\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\\n assembly (\\\"memory-safe\\\") {\\n // load the free memory pointer value\\n let pointer := mload(0x40)\\n\\n // Define length of base (Bsize)\\n mstore(pointer, 0x20)\\n // Define the exponent size (Esize)\\n mstore(add(pointer, 0x20), 0x20)\\n // Define the modulus size (Msize)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base (B)\\n mstore(add(pointer, 0x60), self)\\n // Define the exponent (E)\\n mstore(add(pointer, 0x80), pp1div4)\\n // We save the point of the last argument, it will be override by the result\\n // of the precompile call in order to avoid paying for the memory expansion properly\\n let _result := add(pointer, 0xa0)\\n // Define the modulus (M)\\n mstore(_result, p)\\n\\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\\n if iszero(\\n staticcall(\\n not(0), // amount of gas to send\\n MODEXP_PRECOMPILE, // target\\n pointer, // argsOffset\\n 0xc0, // argsSize (6 * 32 bytes)\\n _result, // retOffset (we override M to avoid paying for the memory expansion)\\n 0x20 // retSize (32 bytes)\\n )\\n ) { revert(0, 0) }\\n\\n result := mload(_result)\\n// result :=addmod(result,0,p)\\n }\\n if(mulmod(result,result,p)!=self){\\n result=_NOTSQUARE;\\n }\\n \\n return result;\\n}\\n /**\\n * /* @dev Convert from affine rep to XYZZ rep\\n */\\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\\n unchecked {\\n P[2] = 1; //ZZ\\n P[3] = 1; //ZZZ\\n P[0] = x0;\\n P[1] = y0;\\n }\\n }\\n\\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \\n\\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\\n\\n y=SqrtMod(y2);\\n if(y==_NOTSQUARE){\\n return _NOTONCURVE;\\n }\\n if((y&1)!=(parity&1)){\\n y=p-y;\\n }\\n }\\n\\n /**\\n * /* @dev Convert from XYZZ rep to affine rep\\n */\\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\\n y1 = mulmod(y, zzzInv, p); //Y/zzz\\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\\n zzzInv = mulmod(_b, _b, p); //1/zz\\n x1 = mulmod(x, zzzInv, p); //X/zz\\n }\\n\\n /**\\n * /* @dev Sutherland2008 doubling\\n */\\n /* The \\\"dbl-2008-s-1\\\" doubling formulas */\\n\\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n assembly {\\n P0 := mulmod(2, y, p) //U = 2*Y1\\n P2 := mulmod(P0, P0, p) // V=U^2\\n P3 := mulmod(x, P2, p) // S = X1*V\\n P1 := mulmod(P0, P2, p) // W=UV\\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\\n }\\n }\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\\n */\\n\\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n if (y1 == 0) {\\n return (x2, y2, 1, 1);\\n }\\n\\n assembly {\\n y1 := sub(p, y1)\\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\\n P0 := mulmod(x2, x2, p) //PP = P^2\\n P1 := mulmod(P0, x2, p) //PPP = P*PP\\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\\n }\\n //end assembly\\n } //end unchecked\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Return the zero curve in XYZZ coordinates.\\n */\\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\\n return (0, 0, 0, 0);\\n }\\n /**\\n * @dev Check if point is the neutral of the curve\\n */\\n\\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\\n return y0 == 0;\\n }\\n /**\\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\\n */\\n\\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\\n return (0, 0);\\n }\\n\\n /**\\n * @dev Check if the curve is the zero curve in affine rep.\\n */\\n // uint256 x, uint256 y)\\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\\n return (y == 0);\\n }\\n\\n /**\\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\\n */\\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\\n return false;\\n }\\n unchecked {\\n uint256 LHS = mulmod(y, y, p); // y^2\\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n\\n return LHS == RHS;\\n }\\n }\\n\\n /**\\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\\n */\\n\\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\\n uint256 zz0;\\n uint256 zzz0;\\n\\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\\n if((x0==x1)&&(y0==y1)) {\\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\\n }\\n else{\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\n }\\n\\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\\n }\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns only x for ECDSA use \\n * */\\n function ecZZ_mulmuladd_S_asm(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 Y;\\n uint256 index = 255;\\n uint256 H0;\\n uint256 H1;\\n\\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n\\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \\n if((H0==0)&&(H1==0))//handling Q=-G\\n {\\n scalar_u=addmod(scalar_u, n-scalar_v, n);\\n scalar_v=0;\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n }\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n X := H0\\n Y := H1\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := H0\\n T2 := H1\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n let T := mload(0x40)\\n mstore(add(T, 0x60), zz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n //Y:=mulmod(Y,zzz,p)//Y/zzz\\n //zz :=mulmod(zz, mload(T),p) //1/z\\n //zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, mload(T), p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return X;\\n }\\n\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns affine representation of point (normalized) \\n * */\\n function ecZZ_mulmuladd(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X, uint256 Y) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 index = 255;\\n uint256[6] memory T;\\n uint256[2] memory H;\\n \\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\\n\\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\\n\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n Y := mload(add(H,32))\\n X := mload(H)\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := mload(H)\\n T2 := mload(add(H,32))\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zzz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n Y:=mulmod(Y,mload(T),p)//Y/zzz\\n zz :=mulmod(zz, mload(T),p) //1/z\\n zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, zz, p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return (X,Y);\\n }\\n\\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\\n //contract at given address dataPointer\\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\\n // the external tool to generate tables from public key is in the /sage directory\\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n unchecked {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n extcodecopy(dataPointer, T, mload(T), 64)\\n let index := sub(zz, 1)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for {} gt(index, 191) { index := add(index, 191) } {\\n //inline Double\\n {\\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(TT1, TT1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n let T1 := mulmod(TT1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n }\\n {\\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n let index2 := sub(index, 64)\\n let T3 :=\\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\\n let index3 := sub(index2, 64)\\n let T2 :=\\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\\n index := sub(index3, 64)\\n let T1 :=\\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T1) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n extcodecopy(dataPointer, T, T1, 64)\\n }\\n\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n\\n // inlined EcZZ_AddN\\n if iszero(zz) {\\n X := mload(T)\\n Y := mload(add(T, 32))\\n zz := 1\\n zzz := 1\\n\\n continue\\n }\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n\\n //special case ecAdd(P,P)=EcDbl\\n if iszero(y2) {\\n if iszero(T2) {\\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n let T4 := mulmod(T2, T2, p)\\n let T1 := mulmod(T4, T2, p) //\\n zz := mulmod(zz, T4, p)\\n //zzz3=V*ZZ1\\n zzz := mulmod(zzz, T1, p) // W=UV/\\n let zz1 := mulmod(X, T4, p)\\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n \\n\\n // improving the extcodecopy trick : append array at end of contract\\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n unchecked {\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n codecopy(T, add(mload(T), dataPointer), 64)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n //index:=add(index,192), restore index, interleaved with loop\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T4) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n codecopy(T, add(T4, dataPointer), 64)\\n\\n // inlined EcZZ_AddN\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n T4 := mulmod(T2, T2, p)\\n T1 := mulmod(T4, T2, p)\\n T2 := mulmod(zz, T4, p) // W=UV\\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\\n let zz1 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\\n zz := T2\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n\\n\\n} //EOF\\n\",\"keccak256\":\"0x7f244805668cc589ae33f18c35c68738db25994c9befbb5d07f28a91fb03ba44\",\"license\":\"MIT\"},\"FreshCryptoLib/utils/Base64Url.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Encode (without '=' padding) \\n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\\n */\\nlibrary Base64Url {\\n /**\\n * @dev Base64Url Encoding Table\\n */\\n string internal constant ENCODING_TABLE =\\n \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\\\";\\n\\n function encode(bytes memory data) internal pure returns (string memory) {\\n if (data.length == 0) return \\\"\\\";\\n\\n // Load the table into memory\\n string memory table = ENCODING_TABLE;\\n\\n string memory result = new string(4 * ((data.length + 2) / 3));\\n\\n // @solidity memory-safe-assembly\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let dataPtr := data\\n let endPtr := add(data, mload(data))\\n } lt(dataPtr, endPtr) {\\n\\n } {\\n dataPtr := add(dataPtr, 3)\\n let input := mload(dataPtr)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n resultPtr := add(resultPtr, 1)\\n }\\n\\n // Remove the padding adjustment logic\\n switch mod(mload(data), 3)\\n case 1 {\\n // Adjust for the last byte of data\\n resultPtr := sub(resultPtr, 2)\\n }\\n case 2 {\\n // Adjust for the last two bytes of data\\n resultPtr := sub(resultPtr, 1)\\n }\\n \\n // Set the correct length of the result string\\n mstore(result, sub(resultPtr, add(result, 32)))\\n }\\n\\n return result; \\n }\\n}\\n\",\"keccak256\":\"0xc9d5fbb0ef9ff0756eb5aabe7a32b2bf0f8f3c533d4451dd5778fe77aee7f0c1\",\"license\":\"Apache-2.0\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title P256Signer\\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This contract is the implementation. It is meant to be used through\\n/// proxy clone.\\ncontract P256Signer {\\n /// @notice The EIP-1271 magic value\\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\\n\\n /// @notice The old EIP-1271 magic value\\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\\n\\n /// @notice Whether the contract has been initialized\\n bool public initialized;\\n\\n /// @notice The x coordinate of the secp256r1 public key\\n uint256 public x;\\n\\n /// @notice The y coordinate of the secp256r1 public key\\n uint256 public y;\\n\\n /// @notice Error message when the signature is invalid\\n error InvalidSignature();\\n\\n /// @notice Error message when the hash is invalid\\n error InvalidHash();\\n\\n /// @notice Error message when the contract is already initialized\\n error AlreadyInitialized();\\n\\n constructor() {\\n initialized = true;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(abi.encode(_hash), _signature);\\n return EIP1271_MAGICVALUE;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @dev This is the old version of the function of EIP-1271 using bytes\\n /// memory instead of bytes32\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\n }\\n\\n struct SignatureLayout {\\n bytes authenticatorData;\\n bytes clientData;\\n uint256 challengeOffset;\\n uint256[2] rs;\\n }\\n\\n /// @notice Validates the signature\\n /// @param data The data signed\\n /// @param _signature The signature\\n function _validate(bytes memory data, bytes calldata _signature) private view {\\n bytes32 _hash = keccak256(data);\\n SignatureLayout calldata signaturePointer;\\n // This code should precalculate the offsets of variables as defined in the layout\\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\\n assembly {\\n signaturePointer := _signature.offset\\n }\\n\\n bool valid = FCL_WebAuthn.checkSignature(\\n signaturePointer.authenticatorData,\\n 0x01,\\n signaturePointer.clientData,\\n _hash,\\n signaturePointer.challengeOffset,\\n signaturePointer.rs,\\n x,\\n y\\n );\\n\\n if (!valid) revert InvalidSignature();\\n }\\n\\n /// @dev This function is only callable once and needs to be called immediately\\n /// after deployment by the factory in the same transaction.\\n /// @param x_ The x coordinate of the public key\\n /// @param y_ The y coordinate of the public key\\n function initialize(uint256 x_, uint256 y_) external {\\n if (initialized) revert AlreadyInitialized();\\n initialized = true;\\n x = x_;\\n y = y_;\\n }\\n}\\n\",\"keccak256\":\"0xfc1b006adb6ace0364918015a1aa64439374f813383bcc71290f6b37b66641e5\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561206a8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cd8565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d53565b61017c565b61008060025481565b61012361011e366004611e3f565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e61565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e61565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ec6565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d24565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ef5565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f53565b67ffffffffffffffff8111156104a7576104a7611d24565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f66565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f76565b90508060208b018301526002826040516105499190611ef5565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f76565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f8f565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611ff560409139905060006003845160026107459190611f53565b61074f9190611fa2565b61075a906004611fdd565b67ffffffffffffffff81111561077257610772611d24565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff831480156108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611580565b909250905081158015610aea575080155b15610b5b577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a0898506000975088158015610b47575087155b15610b5b57600096505050505050506106ef565b600189841c16600189851c1660011b015b80610b8e5760018403935060018a851c1660018a861c1660011b019050610b6c565b50600189841c16600189851c1660011b01955060018603610bf0577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610bff578a96508993505b60038603610c0e578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114d0577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610ef957877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114c5565b60018103610f48577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f57578e93508d92505b60038103610f66578593508492505b89610f7f57509198506001975087965094506114c59050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8809089350806112be57836112be577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114c5565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610c1d565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61154b57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b600080808086611597578585935093505050611605565b846115a9578787935093505050611605565b85881480156115b757508487145b156115d8576115c9888860018061160e565b929a50909850925090506115f2565b6115e788886001808a8a611898565b929a50909850925090505b6115fe88888484611b5d565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b600080600080886000036118b757508492508391506001905080611b50565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b6b84611c12565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611ca157600080fd5b50813567ffffffffffffffff811115611cb957600080fd5b602083019150836020828501011115611cd157600080fd5b9250929050565b600080600060408486031215611ced57600080fd5b83359250602084013567ffffffffffffffff811115611d0b57600080fd5b611d1786828701611c8f565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d6857600080fd5b833567ffffffffffffffff80821115611d8057600080fd5b818601915086601f830112611d9457600080fd5b813581811115611da657611da6611d24565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dec57611dec611d24565b81604052828152896020848701011115611e0557600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e3257600080fd5b50611d1786828701611c8f565b60008060408385031215611e5257600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e9657600080fd5b83018035915067ffffffffffffffff821115611eb157600080fd5b602001915036819003821315611cd157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611f165760208186018101518583015201611efc565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f24565b8183823760009101908152919050565b600060208284031215611f8857600080fd5b5051919050565b818103818111156109da576109da611f24565b600082611fd8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f2456fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa2646970667358221220c618cb60ccea4d134580893ea1be714ea2f3ee81e84f2989f14e663d114ee00a64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cd8565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d53565b61017c565b61008060025481565b61012361011e366004611e3f565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e61565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e61565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ec6565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d24565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ef5565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f53565b67ffffffffffffffff8111156104a7576104a7611d24565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f66565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f76565b90508060208b018301526002826040516105499190611ef5565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f76565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f8f565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611ff560409139905060006003845160026107459190611f53565b61074f9190611fa2565b61075a906004611fdd565b67ffffffffffffffff81111561077257610772611d24565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff831480156108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611580565b909250905081158015610aea575080155b15610b5b577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a0898506000975088158015610b47575087155b15610b5b57600096505050505050506106ef565b600189841c16600189851c1660011b015b80610b8e5760018403935060018a851c1660018a861c1660011b019050610b6c565b50600189841c16600189851c1660011b01955060018603610bf0577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610bff578a96508993505b60038603610c0e578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114d0577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610ef957877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114c5565b60018103610f48577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f57578e93508d92505b60038103610f66578593508492505b89610f7f57509198506001975087965094506114c59050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8809089350806112be57836112be577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114c5565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610c1d565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61154b57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b600080808086611597578585935093505050611605565b846115a9578787935093505050611605565b85881480156115b757508487145b156115d8576115c9888860018061160e565b929a50909850925090506115f2565b6115e788886001808a8a611898565b929a50909850925090505b6115fe88888484611b5d565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b600080600080886000036118b757508492508391506001905080611b50565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b6b84611c12565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611ca157600080fd5b50813567ffffffffffffffff811115611cb957600080fd5b602083019150836020828501011115611cd157600080fd5b9250929050565b600080600060408486031215611ced57600080fd5b83359250602084013567ffffffffffffffff811115611d0b57600080fd5b611d1786828701611c8f565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d6857600080fd5b833567ffffffffffffffff80821115611d8057600080fd5b818601915086601f830112611d9457600080fd5b813581811115611da657611da6611d24565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dec57611dec611d24565b81604052828152896020848701011115611e0557600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e3257600080fd5b50611d1786828701611c8f565b60008060408385031215611e5257600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e9657600080fd5b83018035915067ffffffffffffffff821115611eb157600080fd5b602001915036819003821315611cd157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611f165760208186018101518583015201611efc565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f24565b8183823760009101908152919050565b600060208284031215611f8857600080fd5b5051919050565b818103818111156109da576109da611f24565b600082611fd8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f2456fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa2646970667358221220c618cb60ccea4d134580893ea1be714ea2f3ee81e84f2989f14e663d114ee00a64736f6c63430008140033", + "devdoc": { + "details": "This contract is the implementation. It is meant to be used through proxy clone.", + "kind": "dev", + "methods": { + "initialize(uint256,uint256)": { + "details": "This function is only callable once and needs to be called immediately after deployment by the factory in the same transaction.", + "params": { + "x_": "The x coordinate of the public key", + "y_": "The y coordinate of the public key" + } + }, + "isValidSignature(bytes,bytes)": { + "details": "This is the old version of the function of EIP-1271 using bytes memory instead of bytes32", + "params": { + "_hash": "The hash of the data signed", + "_signature": "The signature" + }, + "returns": { + "_0": "The EIP-1271 magic value" + } + }, + "isValidSignature(bytes32,bytes)": { + "params": { + "_hash": "The hash of the data signed", + "_signature": "The signature" + }, + "returns": { + "_0": "The EIP-1271 magic value" + } + } + }, + "title": "P256Signer", + "version": 1 + }, + "userdoc": { + "errors": { + "AlreadyInitialized()": [ + { + "notice": "Error message when the contract is already initialized" + } + ], + "InvalidHash()": [ + { + "notice": "Error message when the hash is invalid" + } + ], + "InvalidSignature()": [ + { + "notice": "Error message when the signature is invalid" + } + ] + }, + "kind": "user", + "methods": { + "initialized()": { + "notice": "Whether the contract has been initialized" + }, + "isValidSignature(bytes,bytes)": { + "notice": "Verifies that the signer is the owner of the secp256r1 public key." + }, + "isValidSignature(bytes32,bytes)": { + "notice": "Verifies that the signer is the owner of the secp256r1 public key." + }, + "x()": { + "notice": "The x coordinate of the secp256r1 public key" + }, + "y()": { + "notice": "The y coordinate of the secp256r1 public key" + } + }, + "notice": "A contract used to verify ECDSA signatures over secp256r1 through EIP-1271 of Webauthn payloads.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2870, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 2873, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "x", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 2876, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "y", + "offset": 0, + "slot": "2", + "type": "t_uint256" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/base_production/P256SignerFactory.json b/deployments/base_production/P256SignerFactory.json new file mode 100644 index 0000000..407d3b7 --- /dev/null +++ b/deployments/base_production/P256SignerFactory.json @@ -0,0 +1,137 @@ +{ + "address": "0xa726C1619bB28cc0e1303eFEa80BbAF9FE42389f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "x", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "y", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "NewSignerCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "y", + "type": "uint256" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xd344d6ccd7016201ee5d677ae3d94b6e7da3fd325c55b08fc05e7816b2d5b57b", + "receipt": { + "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", + "from": "0x61f2ad863873d2466B64cef9cdC65361F98A65D3", + "contractAddress": null, + "transactionIndex": 4, + "gasUsed": "195440", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x0770727b9e87fcec5672815d7ec98c7dd9b22a1bb64664244a3b756bbba77dda", + "transactionHash": "0xd344d6ccd7016201ee5d677ae3d94b6e7da3fd325c55b08fc05e7816b2d5b57b", + "logs": [], + "blockNumber": 12379003, + "cumulativeGasUsed": "628803", + "status": 1, + "byzantium": true + }, + "args": [ + "0x93ae54DAE3A266d2F7197d118e1B3A89429ba55F" + ], + "numDeployments": 1, + "solcInputHash": "01c9a206ce5ca6951fd356b6a1b5a7d7", + "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"NewSignerCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"create(uint256,uint256)\":{\"params\":{\"x\":\"The x coordinate of the public key\",\"y\":\"The y coordinate of the public key\"}}},\"title\":\"P256SignerFactory\",\"version\":1},\"userdoc\":{\"events\":{\"NewSignerCreated(uint256,uint256,address)\":{\"notice\":\"Emitted when a new P256Signer proxy contract is created\"}},\"kind\":\"user\",\"methods\":{\"create(uint256,uint256)\":{\"notice\":\"Creates a new P256Signer proxy contract\"},\"implementation()\":{\"notice\":\"The implementation address of the P256Signer contract\"}},\"notice\":\"Factory contract for creating proxies for P256Signer\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/P256SignerFactory.sol\":\"P256SignerFactory\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"FreshCryptoLib/FCL_Webauthn.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_elliptic.sol\\n///*\\n///*\\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\nimport {FCL_ecdsa} from \\\"./FCL_ecdsa.sol\\\";\\n\\nimport {FCL_ecdsa_utils} from \\\"./FCL_ecdsa_utils.sol\\\";\\n\\nlibrary FCL_WebAuthn {\\n error InvalidAuthenticatorData();\\n error InvalidClientData();\\n error InvalidSignature();\\n\\n function WebAuthn_format(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata // rs\\n ) internal pure returns (bytes32 result) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n {\\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\\n revert InvalidAuthenticatorData();\\n }\\n // Verify that clientData commits to the expected client challenge\\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\\n bytes memory challengeExtracted = new bytes(\\n bytes(challengeEncoded).length\\n );\\n\\n assembly {\\n calldatacopy(\\n add(challengeExtracted, 32),\\n add(clientData.offset, clientChallengeDataOffset),\\n mload(challengeExtracted)\\n )\\n }\\n\\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\\n assembly {\\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\\n }\\n\\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\\n revert InvalidClientData();\\n }\\n } //avoid stack full\\n\\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\\n\\n assembly {\\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\\n }\\n\\n bytes32 more = sha256(clientData);\\n assembly {\\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\\n }\\n\\n return sha256(verifyData);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256[2] calldata Q\\n ) internal view returns (bool) {\\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 Qx,\\n uint256 Qy\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\\n\\n return result;\\n }\\n\\n function checkSignature_prec(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n address dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\\n\\n return result;\\n }\\n\\n //beware that this implementation will not be compliant with EOF\\n function checkSignature_hackmem(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc2811ef6e17ea1d5509a3d3f7d5af5e56583347b36093d05530425d7c1316dd6\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n /**\\n * @dev ECDSA verification, given , signature, and public key, no calldata version\\n */\\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\\n\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n \\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n\\n x1= addmod(x1, n-r,n );\\n \\n return x1 == 0;\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n \\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n}\\n\",\"keccak256\":\"0x679d2e9a655cd7e156a0cfc24de0aca88d4e0b34a8e0dfe6a599f23af092f5a2\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa_utils.sol\":{\"content\":\"\\n//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa_utils {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n x1= addmod(x1, n-r,n );\\n \\n \\n return x1 == 0;\\n }\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\n return ecdsa_verify(message, rs, Q[0], Q[1]);\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n\\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\\n //K is nonce, kpriv is private key\\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\\n {\\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \\n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n //ecdsa key derivation\\n //kpriv is private key return (x,y) coordinates of associated Pubkey\\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\\n {\\n \\n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\\n \\n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\\n {\\n y=FCL_Elliptic_ZZ.p-y;\\n } \\n\\n }\\n \\n //precomputations for 8 dimensional trick\\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\\n {\\n \\n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\\n \\n //the trivial private keys 1 and -1 are forbidden\\n if(Qx==FCL_Elliptic_ZZ.gx)\\n {\\n revert();\\n }\\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\\n \\n Pow64_PQ[4][0]=Qx;\\n Pow64_PQ[4][1]=Qy;\\n \\n /* raise to multiplication by 64 by 6 consecutive doubling*/\\n for(uint j=1;j<4;j++){\\n uint256 x;\\n uint256 y;\\n uint256 zz;\\n uint256 zzz;\\n \\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\\n \\t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\\n \\t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n\\n \\tfor(uint i=0;i<63;i++){\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t}\\n }\\n \\n /* neutral point */\\n Prec[0][0]=0;\\n Prec[0][1]=0;\\n \\n \\t\\n for(uint i=1;i<256;i++)\\n { \\n Prec[i][0]=0;\\n Prec[i][1]=0;\\n \\n for(uint j=0;j<8;j++)\\n {\\n \\tif( (i&(1<=0.8.19 <0.9.0;\\n\\nlibrary FCL_Elliptic_ZZ {\\n // Set parameters for curve sec256r1.\\n\\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\\n //curve prime field modulus\\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n //short weierstrass first coefficient\\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n //short weierstrass second coefficient\\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n //generating point affine coordinates\\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n //curve order (number of points)\\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\\n /* -2 mod n constant, used to speed up inversion*/\\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\\n\\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n //P+1 div 4\\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\\n //arbitrary constant to express no quadratic residuosity\\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n /**\\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\\n */\\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2modn)\\n mstore(add(pointer, 0xa0), n)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n /**\\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\\n */\\n\\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2)\\n mstore(add(pointer, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n\\n //Coron projective shuffling, take as input alpha as blinding factor\\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n \\n uint256 alpha2=mulmod(alpha,alpha,p);\\n \\n x3=mulmod(alpha2, x,p); //alpha^-2.x\\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\\n\\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\\n \\n return (x3, y3, zz3, zzz3);\\n }\\n\\n\\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\\n u2=addmod(u2, p-u1, p);// P = U2-U1\\n x1=mulmod(u2, u2, p);//PP\\n x2=mulmod(x1, u2, p);//PPP\\n \\n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \\n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\\n\\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \\n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\\n\\n return (x3, y3, zz3, zzz3);\\n }\\n\\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\\n/// @param self The integer of which to find the modular inverse\\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\\n\\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\\n assembly (\\\"memory-safe\\\") {\\n // load the free memory pointer value\\n let pointer := mload(0x40)\\n\\n // Define length of base (Bsize)\\n mstore(pointer, 0x20)\\n // Define the exponent size (Esize)\\n mstore(add(pointer, 0x20), 0x20)\\n // Define the modulus size (Msize)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base (B)\\n mstore(add(pointer, 0x60), self)\\n // Define the exponent (E)\\n mstore(add(pointer, 0x80), pp1div4)\\n // We save the point of the last argument, it will be override by the result\\n // of the precompile call in order to avoid paying for the memory expansion properly\\n let _result := add(pointer, 0xa0)\\n // Define the modulus (M)\\n mstore(_result, p)\\n\\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\\n if iszero(\\n staticcall(\\n not(0), // amount of gas to send\\n MODEXP_PRECOMPILE, // target\\n pointer, // argsOffset\\n 0xc0, // argsSize (6 * 32 bytes)\\n _result, // retOffset (we override M to avoid paying for the memory expansion)\\n 0x20 // retSize (32 bytes)\\n )\\n ) { revert(0, 0) }\\n\\n result := mload(_result)\\n// result :=addmod(result,0,p)\\n }\\n if(mulmod(result,result,p)!=self){\\n result=_NOTSQUARE;\\n }\\n \\n return result;\\n}\\n /**\\n * /* @dev Convert from affine rep to XYZZ rep\\n */\\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\\n unchecked {\\n P[2] = 1; //ZZ\\n P[3] = 1; //ZZZ\\n P[0] = x0;\\n P[1] = y0;\\n }\\n }\\n\\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \\n\\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\\n\\n y=SqrtMod(y2);\\n if(y==_NOTSQUARE){\\n return _NOTONCURVE;\\n }\\n if((y&1)!=(parity&1)){\\n y=p-y;\\n }\\n }\\n\\n /**\\n * /* @dev Convert from XYZZ rep to affine rep\\n */\\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\\n y1 = mulmod(y, zzzInv, p); //Y/zzz\\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\\n zzzInv = mulmod(_b, _b, p); //1/zz\\n x1 = mulmod(x, zzzInv, p); //X/zz\\n }\\n\\n /**\\n * /* @dev Sutherland2008 doubling\\n */\\n /* The \\\"dbl-2008-s-1\\\" doubling formulas */\\n\\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n assembly {\\n P0 := mulmod(2, y, p) //U = 2*Y1\\n P2 := mulmod(P0, P0, p) // V=U^2\\n P3 := mulmod(x, P2, p) // S = X1*V\\n P1 := mulmod(P0, P2, p) // W=UV\\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\\n }\\n }\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\\n */\\n\\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n if (y1 == 0) {\\n return (x2, y2, 1, 1);\\n }\\n\\n assembly {\\n y1 := sub(p, y1)\\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\\n P0 := mulmod(x2, x2, p) //PP = P^2\\n P1 := mulmod(P0, x2, p) //PPP = P*PP\\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\\n }\\n //end assembly\\n } //end unchecked\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Return the zero curve in XYZZ coordinates.\\n */\\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\\n return (0, 0, 0, 0);\\n }\\n /**\\n * @dev Check if point is the neutral of the curve\\n */\\n\\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\\n return y0 == 0;\\n }\\n /**\\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\\n */\\n\\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\\n return (0, 0);\\n }\\n\\n /**\\n * @dev Check if the curve is the zero curve in affine rep.\\n */\\n // uint256 x, uint256 y)\\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\\n return (y == 0);\\n }\\n\\n /**\\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\\n */\\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\\n return false;\\n }\\n unchecked {\\n uint256 LHS = mulmod(y, y, p); // y^2\\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n\\n return LHS == RHS;\\n }\\n }\\n\\n /**\\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\\n */\\n\\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\\n uint256 zz0;\\n uint256 zzz0;\\n\\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\\n if((x0==x1)&&(y0==y1)) {\\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\\n }\\n else{\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\n }\\n\\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\\n }\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns only x for ECDSA use \\n * */\\n function ecZZ_mulmuladd_S_asm(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 Y;\\n uint256 index = 255;\\n uint256 H0;\\n uint256 H1;\\n\\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n\\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \\n if((H0==0)&&(H1==0))//handling Q=-G\\n {\\n scalar_u=addmod(scalar_u, n-scalar_v, n);\\n scalar_v=0;\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n }\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n X := H0\\n Y := H1\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := H0\\n T2 := H1\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n let T := mload(0x40)\\n mstore(add(T, 0x60), zz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n //Y:=mulmod(Y,zzz,p)//Y/zzz\\n //zz :=mulmod(zz, mload(T),p) //1/z\\n //zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, mload(T), p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return X;\\n }\\n\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns affine representation of point (normalized) \\n * */\\n function ecZZ_mulmuladd(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X, uint256 Y) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 index = 255;\\n uint256[6] memory T;\\n uint256[2] memory H;\\n \\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\\n\\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\\n\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n Y := mload(add(H,32))\\n X := mload(H)\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := mload(H)\\n T2 := mload(add(H,32))\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zzz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n Y:=mulmod(Y,mload(T),p)//Y/zzz\\n zz :=mulmod(zz, mload(T),p) //1/z\\n zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, zz, p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return (X,Y);\\n }\\n\\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\\n //contract at given address dataPointer\\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\\n // the external tool to generate tables from public key is in the /sage directory\\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n unchecked {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n extcodecopy(dataPointer, T, mload(T), 64)\\n let index := sub(zz, 1)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for {} gt(index, 191) { index := add(index, 191) } {\\n //inline Double\\n {\\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(TT1, TT1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n let T1 := mulmod(TT1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n }\\n {\\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n let index2 := sub(index, 64)\\n let T3 :=\\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\\n let index3 := sub(index2, 64)\\n let T2 :=\\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\\n index := sub(index3, 64)\\n let T1 :=\\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T1) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n extcodecopy(dataPointer, T, T1, 64)\\n }\\n\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n\\n // inlined EcZZ_AddN\\n if iszero(zz) {\\n X := mload(T)\\n Y := mload(add(T, 32))\\n zz := 1\\n zzz := 1\\n\\n continue\\n }\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n\\n //special case ecAdd(P,P)=EcDbl\\n if iszero(y2) {\\n if iszero(T2) {\\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n let T4 := mulmod(T2, T2, p)\\n let T1 := mulmod(T4, T2, p) //\\n zz := mulmod(zz, T4, p)\\n //zzz3=V*ZZ1\\n zzz := mulmod(zzz, T1, p) // W=UV/\\n let zz1 := mulmod(X, T4, p)\\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n \\n\\n // improving the extcodecopy trick : append array at end of contract\\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n unchecked {\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n codecopy(T, add(mload(T), dataPointer), 64)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n //index:=add(index,192), restore index, interleaved with loop\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T4) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n codecopy(T, add(T4, dataPointer), 64)\\n\\n // inlined EcZZ_AddN\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n T4 := mulmod(T2, T2, p)\\n T1 := mulmod(T4, T2, p)\\n T2 := mulmod(zz, T4, p) // W=UV\\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\\n let zz1 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\\n zz := T2\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n\\n\\n} //EOF\\n\",\"keccak256\":\"0x7f244805668cc589ae33f18c35c68738db25994c9befbb5d07f28a91fb03ba44\",\"license\":\"MIT\"},\"FreshCryptoLib/utils/Base64Url.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Encode (without '=' padding) \\n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\\n */\\nlibrary Base64Url {\\n /**\\n * @dev Base64Url Encoding Table\\n */\\n string internal constant ENCODING_TABLE =\\n \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\\\";\\n\\n function encode(bytes memory data) internal pure returns (string memory) {\\n if (data.length == 0) return \\\"\\\";\\n\\n // Load the table into memory\\n string memory table = ENCODING_TABLE;\\n\\n string memory result = new string(4 * ((data.length + 2) / 3));\\n\\n // @solidity memory-safe-assembly\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let dataPtr := data\\n let endPtr := add(data, mload(data))\\n } lt(dataPtr, endPtr) {\\n\\n } {\\n dataPtr := add(dataPtr, 3)\\n let input := mload(dataPtr)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n resultPtr := add(resultPtr, 1)\\n }\\n\\n // Remove the padding adjustment logic\\n switch mod(mload(data), 3)\\n case 1 {\\n // Adjust for the last byte of data\\n resultPtr := sub(resultPtr, 2)\\n }\\n case 2 {\\n // Adjust for the last two bytes of data\\n resultPtr := sub(resultPtr, 1)\\n }\\n \\n // Set the correct length of the result string\\n mstore(result, sub(resultPtr, add(result, 32)))\\n }\\n\\n return result; \\n }\\n}\\n\",\"keccak256\":\"0xc9d5fbb0ef9ff0756eb5aabe7a32b2bf0f8f3c533d4451dd5778fe77aee7f0c1\",\"license\":\"Apache-2.0\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title P256Signer\\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This contract is the implementation. It is meant to be used through\\n/// proxy clone.\\ncontract P256Signer {\\n /// @notice The EIP-1271 magic value\\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\\n\\n /// @notice The old EIP-1271 magic value\\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\\n\\n /// @notice Whether the contract has been initialized\\n bool public initialized;\\n\\n /// @notice The x coordinate of the secp256r1 public key\\n uint256 public x;\\n\\n /// @notice The y coordinate of the secp256r1 public key\\n uint256 public y;\\n\\n /// @notice Error message when the signature is invalid\\n error InvalidSignature();\\n\\n /// @notice Error message when the hash is invalid\\n error InvalidHash();\\n\\n /// @notice Error message when the contract is already initialized\\n error AlreadyInitialized();\\n\\n constructor() {\\n initialized = true;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(abi.encode(_hash), _signature);\\n return EIP1271_MAGICVALUE;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @dev This is the old version of the function of EIP-1271 using bytes\\n /// memory instead of bytes32\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\n }\\n\\n struct SignatureLayout {\\n bytes authenticatorData;\\n bytes clientData;\\n uint256 challengeOffset;\\n uint256[2] rs;\\n }\\n\\n /// @notice Validates the signature\\n /// @param data The data signed\\n /// @param _signature The signature\\n function _validate(bytes memory data, bytes calldata _signature) private view {\\n bytes32 _hash = keccak256(data);\\n SignatureLayout calldata signaturePointer;\\n // This code should precalculate the offsets of variables as defined in the layout\\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\\n assembly {\\n signaturePointer := _signature.offset\\n }\\n\\n bool valid = FCL_WebAuthn.checkSignature(\\n signaturePointer.authenticatorData,\\n 0x01,\\n signaturePointer.clientData,\\n _hash,\\n signaturePointer.challengeOffset,\\n signaturePointer.rs,\\n x,\\n y\\n );\\n\\n if (!valid) revert InvalidSignature();\\n }\\n\\n /// @dev This function is only callable once and needs to be called immediately\\n /// after deployment by the factory in the same transaction.\\n /// @param x_ The x coordinate of the public key\\n /// @param y_ The y coordinate of the public key\\n function initialize(uint256 x_, uint256 y_) external {\\n if (initialized) revert AlreadyInitialized();\\n initialized = true;\\n x = x_;\\n y = y_;\\n }\\n}\\n\",\"keccak256\":\"0xfc1b006adb6ace0364918015a1aa64439374f813383bcc71290f6b37b66641e5\"},\"contracts/P256SignerFactory.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {P256Signer} from \\\"./P256Signer.sol\\\";\\nimport \\\"solady/src/utils/LibClone.sol\\\";\\n\\n/// @title P256SignerFactory\\n/// @notice Factory contract for creating proxies for P256Signer\\ncontract P256SignerFactory {\\n /// @notice The implementation address of the P256Signer contract\\n address public immutable implementation;\\n\\n constructor(address implementation_) {\\n implementation = implementation_;\\n }\\n\\n /// @notice Emitted when a new P256Signer proxy contract is created\\n event NewSignerCreated(uint256 indexed x, uint256 indexed y, address signer);\\n\\n /// @notice Creates a new P256Signer proxy contract\\n /// @param x The x coordinate of the public key\\n /// @param y The y coordinate of the public key\\n function create(uint256 x, uint256 y) external returns (address) {\\n bytes32 salt = keccak256(abi.encodePacked(x, y));\\n address signer = LibClone.cloneDeterministic(implementation, salt);\\n P256Signer(signer).initialize(x, y);\\n emit NewSignerCreated(x, y, signer);\\n return signer;\\n }\\n}\\n\",\"keccak256\":\"0x3bdac08bf7a1c4c1621474b10733f74a9487359212705bbca42ec678aa549a53\"},\"solady/src/utils/LibClone.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Minimal proxy library.\\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)\\n/// @author Minimal proxy by 0age (https://github.com/0age)\\n/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie\\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\\n///\\n/// @dev Minimal proxy:\\n/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,\\n/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,\\n/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.\\n///\\n/// @dev Minimal proxy (PUSH0 variant):\\n/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.\\n/// It is optimized first for minimal runtime gas, then for minimal bytecode.\\n/// The PUSH0 clone functions are intentionally postfixed with a jarring \\\"_PUSH0\\\" as\\n/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.\\n/// Please use with caution.\\n///\\n/// @dev Clones with immutable args (CWIA):\\n/// The implementation of CWIA here implements a `receive()` method that emits the\\n/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,\\n/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards\\n/// composability. The minimal proxy implementation does not offer this feature.\\nlibrary LibClone {\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* CUSTOM ERRORS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Unable to deploy the clone.\\n error DeploymentFailed();\\n\\n /// @dev The salt must start with either the zero address or the caller.\\n error SaltDoesNotStartWithCaller();\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* MINIMAL PROXY OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a clone of `implementation`.\\n function clone(address implementation) internal returns (address instance) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n /**\\n * --------------------------------------------------------------------------+\\n * CREATION (9 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * 60 runSize | PUSH1 runSize | r | |\\n * 3d | RETURNDATASIZE | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * --------------------------------------------------------------------------|\\n * RUNTIME (44 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * |\\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | 0 | |\\n * 3d | RETURNDATASIZE | 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 0 0 | |\\n * |\\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |\\n * 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |\\n * |\\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |\\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |\\n * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |\\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |\\n * |\\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |\\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |\\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |\\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\\n * |\\n * 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |\\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\\n * |\\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * --------------------------------------------------------------------------+\\n */\\n\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n instance := create(0, 0x0c, 0x35)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Deploys a deterministic clone of `implementation` with `salt`.\\n function cloneDeterministic(address implementation, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n instance := create2(0, 0x0c, 0x35, salt)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the clone of `implementation`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash(address implementation) internal pure returns (bytes32 hash) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n hash := keccak256(0x0c, 0x35)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic clone of `implementation`,\\n /// with `salt` by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)\\n internal\\n pure\\n returns (address predicted)\\n {\\n bytes32 hash = initCodeHash(implementation);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a PUSH0 clone of `implementation`.\\n function clone_PUSH0(address implementation) internal returns (address instance) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n /**\\n * --------------------------------------------------------------------------+\\n * CREATION (9 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * 60 runSize | PUSH1 runSize | r | |\\n * 5f | PUSH0 | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 5f | PUSH0 | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * --------------------------------------------------------------------------|\\n * RUNTIME (45 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * |\\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\\n * 5f | PUSH0 | 0 | |\\n * 5f | PUSH0 | 0 0 | |\\n * |\\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 | |\\n * 5f | PUSH0 | 0 cds 0 0 | |\\n * 5f | PUSH0 | 0 0 cds 0 0 | |\\n * 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |\\n * |\\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |\\n * 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |\\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |\\n * 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |\\n * f4 | DELEGATECALL | success | [0..cds): calldata |\\n * |\\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success | [0..cds): calldata |\\n * 5f | PUSH0 | 0 rds success | [0..cds): calldata |\\n * 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |\\n * 3e | RETURNDATACOPY | success | [0..rds): returndata |\\n * |\\n * 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |\\n * 57 | JUMPI | | [0..rds): returndata |\\n * |\\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | | [0..rds): returndata |\\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * --------------------------------------------------------------------------+\\n */\\n\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n instance := create(0, 0x0e, 0x36)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\\n function cloneDeterministic_PUSH0(address implementation, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n instance := create2(0, 0x0e, 0x36, salt)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n hash := keccak256(0x0e, 0x36)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,\\n /// with `salt` by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress_PUSH0(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n bytes32 hash = initCodeHash_PUSH0(implementation);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* CLONES WITH IMMUTABLE ARGS OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a minimal proxy with `implementation`,\\n /// using immutable arguments encoded in `data`.\\n ///\\n /// Note: This implementation of CWIA differs from the original implementation.\\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\\n function clone(address implementation, bytes memory data) internal returns (address instance) {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n // The `creationSize` is `extraLength + 108`\\n // The `runSize` is `creationSize - 10`.\\n\\n /**\\n * ---------------------------------------------------------------------------------------------------+\\n * CREATION (10 bytes) |\\n * ---------------------------------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * ---------------------------------------------------------------------------------------------------|\\n * 61 runSize | PUSH2 runSize | r | |\\n * 3d | RETURNDATASIZE | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * ---------------------------------------------------------------------------------------------------|\\n * RUNTIME (98 bytes + extraLength) |\\n * ---------------------------------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * ---------------------------------------------------------------------------------------------------|\\n * |\\n * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds | |\\n * 60 0x2c | PUSH1 0x2c | 0x2c cds | |\\n * 57 | JUMPI | | |\\n * 34 | CALLVALUE | cv | |\\n * 3d | RETURNDATASIZE | 0 cv | |\\n * 52 | MSTORE | | [0..0x20): callvalue |\\n * 7f sig | PUSH32 0x9e.. | sig | [0..0x20): callvalue |\\n * 59 | MSIZE | 0x20 sig | [0..0x20): callvalue |\\n * 3d | RETURNDATASIZE | 0 0x20 sig | [0..0x20): callvalue |\\n * a1 | LOG1 | | [0..0x20): callvalue |\\n * 00 | STOP | | [0..0x20): callvalue |\\n * 5b | JUMPDEST | | |\\n * |\\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds | |\\n * 3d | RETURNDATASIZE | 0 cds | |\\n * 3d | RETURNDATASIZE | 0 0 cds | |\\n * 37 | CALLDATACOPY | | [0..cds): calldata |\\n * |\\n * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata |\\n * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata |\\n * |\\n * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata |\\n * 60 0x62 | PUSH1 0x62 | 0x62 e e 0 0 0 0 | [0..cds): calldata |\\n * 36 | CALLDATASIZE | cds 0x62 e e 0 0 0 0 | [0..cds): calldata |\\n * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * |\\n * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * |\\n * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\\n * |\\n * 60 0x60 | PUSH1 0x60 | 0x60 success 0 rds | [0..rds): returndata |\\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\\n * |\\n * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * ---------------------------------------------------------------------------------------------------+\\n */\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\\n // The actual EVM limit may be smaller and may change over time.\\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Create the instance.\\n instance := create(0, sub(data, 0x4c), add(extraLength, 0x6c))\\n\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Deploys a deterministic clone of `implementation`,\\n /// using immutable arguments encoded in `data`, with `salt`.\\n ///\\n /// Note: This implementation of CWIA differs from the original implementation.\\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\\n function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\\n // The actual EVM limit may be smaller and may change over time.\\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Create the instance.\\n instance := create2(0, sub(data, 0x4c), add(extraLength, 0x6c), salt)\\n\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the clone of `implementation`\\n /// using immutable arguments encoded in `data`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash(address implementation, bytes memory data)\\n internal\\n pure\\n returns (bytes32 hash)\\n {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.\\n // The actual EVM limit may be smaller and may change over time.\\n returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n sub(data, 0x5a),\\n or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Compute and store the bytecode hash.\\n hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic clone of\\n /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(\\n address implementation,\\n bytes memory data,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n bytes32 hash = initCodeHash(implementation, data);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* OTHER OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Returns the address when a contract with initialization code hash,\\n /// `hash`, is deployed with `salt`, by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)\\n internal\\n pure\\n returns (address predicted)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Compute and store the bytecode hash.\\n mstore8(0x00, 0xff) // Write the prefix.\\n mstore(0x35, hash)\\n mstore(0x01, shl(96, deployer))\\n mstore(0x15, salt)\\n predicted := keccak256(0x00, 0x55)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x35, 0)\\n }\\n }\\n\\n /// @dev Reverts if `salt` does not start with either the zero address or the caller.\\n function checkStartsWithCaller(bytes32 salt) internal view {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // If the salt does not start with the zero address or the caller.\\n if iszero(or(iszero(shr(96, salt)), eq(caller(), shr(96, salt)))) {\\n // Store the function selector of `SaltDoesNotStartWithCaller()`.\\n mstore(0x00, 0x2f634836)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x159b64c65da9e6efe93b8df8c6bb1c7672a7511dcaba414aaa3e447f6d7065e6\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d8b0407d1a28cd9f0ad691ad81667640a0419d8054ee5121c474b80b2ce9bf0064736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d8b0407d1a28cd9f0ad691ad81667640a0419d8054ee5121c474b80b2ce9bf0064736f6c63430008140033", + "devdoc": { + "kind": "dev", + "methods": { + "create(uint256,uint256)": { + "params": { + "x": "The x coordinate of the public key", + "y": "The y coordinate of the public key" + } + } + }, + "title": "P256SignerFactory", + "version": 1 + }, + "userdoc": { + "events": { + "NewSignerCreated(uint256,uint256,address)": { + "notice": "Emitted when a new P256Signer proxy contract is created" + } + }, + "kind": "user", + "methods": { + "create(uint256,uint256)": { + "notice": "Creates a new P256Signer proxy contract" + }, + "implementation()": { + "notice": "The implementation address of the P256Signer contract" + } + }, + "notice": "Factory contract for creating proxies for P256Signer", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/base_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json b/deployments/base_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json new file mode 100644 index 0000000..2c01ac3 --- /dev/null +++ b/deployments/base_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json @@ -0,0 +1,57 @@ +{ + "language": "Solidity", + "sources": { + "contracts/P256Signer.sol": { + "content": "pragma solidity ^0.8.0;\n\nimport {FCL_WebAuthn} from \"FreshCryptoLib/FCL_Webauthn.sol\";\n\n/// @title P256Signer\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\n/// EIP-1271 of Webauthn payloads.\n/// @dev This contract is the implementation. It is meant to be used through\n/// proxy clone.\ncontract P256Signer {\n /// @notice The EIP-1271 magic value\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\n\n /// @notice The old EIP-1271 magic value\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\n\n /// @notice Whether the contract has been initialized\n bool public initialized;\n\n /// @notice The x coordinate of the secp256r1 public key\n uint256 public x;\n\n /// @notice The y coordinate of the secp256r1 public key\n uint256 public y;\n\n /// @notice Error message when the signature is invalid\n error InvalidSignature();\n\n /// @notice Error message when the hash is invalid\n error InvalidHash();\n\n /// @notice Error message when the contract is already initialized\n error AlreadyInitialized();\n\n constructor() {\n initialized = true;\n }\n\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\n /// @param _hash The hash of the data signed\n /// @param _signature The signature\n /// @return The EIP-1271 magic value\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\n _validate(abi.encode(_hash), _signature);\n return EIP1271_MAGICVALUE;\n }\n\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\n /// @dev This is the old version of the function of EIP-1271 using bytes\n /// memory instead of bytes32\n /// @param _hash The hash of the data signed\n /// @param _signature The signature\n /// @return The EIP-1271 magic value\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\n _validate(_hash, _signature);\n return OLD_EIP1271_MAGICVALUE;\n }\n\n struct SignatureLayout {\n bytes authenticatorData;\n bytes clientData;\n uint256 challengeOffset;\n uint256[2] rs;\n }\n\n /// @notice Validates the signature\n /// @param data The data signed\n /// @param _signature The signature\n function _validate(bytes memory data, bytes calldata _signature) private view {\n bytes32 _hash = keccak256(data);\n SignatureLayout calldata signaturePointer;\n // This code should precalculate the offsets of variables as defined in the layout\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\n assembly {\n signaturePointer := _signature.offset\n }\n\n bool valid = FCL_WebAuthn.checkSignature(\n signaturePointer.authenticatorData,\n 0x01,\n signaturePointer.clientData,\n _hash,\n signaturePointer.challengeOffset,\n signaturePointer.rs,\n x,\n y\n );\n\n if (!valid) revert InvalidSignature();\n }\n\n /// @dev This function is only callable once and needs to be called immediately\n /// after deployment by the factory in the same transaction.\n /// @param x_ The x coordinate of the public key\n /// @param y_ The y coordinate of the public key\n function initialize(uint256 x_, uint256 y_) external {\n if (initialized) revert AlreadyInitialized();\n initialized = true;\n x = x_;\n y = y_;\n }\n}\n" + }, + "contracts/P256SignerFactory.sol": { + "content": "pragma solidity ^0.8.0;\n\nimport {P256Signer} from \"./P256Signer.sol\";\nimport \"solady/src/utils/LibClone.sol\";\n\n/// @title P256SignerFactory\n/// @notice Factory contract for creating proxies for P256Signer\ncontract P256SignerFactory {\n /// @notice The implementation address of the P256Signer contract\n address public immutable implementation;\n\n constructor(address implementation_) {\n implementation = implementation_;\n }\n\n /// @notice Emitted when a new P256Signer proxy contract is created\n event NewSignerCreated(uint256 indexed x, uint256 indexed y, address signer);\n\n /// @notice Creates a new P256Signer proxy contract\n /// @param x The x coordinate of the public key\n /// @param y The y coordinate of the public key\n function create(uint256 x, uint256 y) external returns (address) {\n bytes32 salt = keccak256(abi.encodePacked(x, y));\n address signer = LibClone.cloneDeterministic(implementation, salt);\n P256Signer(signer).initialize(x, y);\n emit NewSignerCreated(x, y, signer);\n return signer;\n }\n}\n" + }, + "FreshCryptoLib/FCL_ecdsa_utils.sol": { + "content": "\n//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n// |__/|_|\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_ecdsa.sol\n///*\n///*\n///* DESCRIPTION: ecdsa verification implementation\n///*\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\n\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\n\n\n\nlibrary FCL_ecdsa_utils {\n // Set parameters for curve sec256r1.public\n //curve order (number of points)\n uint256 constant n = FCL_Elliptic_ZZ.n;\n \n /**\n * @dev ECDSA verification, given , signature, and public key.\n */\n\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return false;\n }\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\n return false;\n }\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\n uint256 x1;\n\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\n x1= addmod(x1, n-r,n );\n \n \n return x1 == 0;\n }\n\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\n return ecdsa_verify(message, rs, Q[0], Q[1]);\n }\n\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\n {\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return address(0);\n }\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\n\n uint256 Qx;\n uint256 Qy;\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\n\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\n }\n\n\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\n //K is nonce, kpriv is private key\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\n {\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\n\n \n if(r==0||s==0){\n revert();\n }\n\n\n }\n\n //ecdsa key derivation\n //kpriv is private key return (x,y) coordinates of associated Pubkey\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\n {\n \n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\n \n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\n {\n y=FCL_Elliptic_ZZ.p-y;\n } \n\n }\n \n //precomputations for 8 dimensional trick\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\n {\n \n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\n \n //the trivial private keys 1 and -1 are forbidden\n if(Qx==FCL_Elliptic_ZZ.gx)\n {\n revert();\n }\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\n \n Pow64_PQ[4][0]=Qx;\n Pow64_PQ[4][1]=Qy;\n \n /* raise to multiplication by 64 by 6 consecutive doubling*/\n for(uint j=1;j<4;j++){\n uint256 x;\n uint256 y;\n uint256 zz;\n uint256 zzz;\n \n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\n \t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\n \t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n\n \tfor(uint i=0;i<63;i++){\n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n \t}\n }\n \n /* neutral point */\n Prec[0][0]=0;\n Prec[0][1]=0;\n \n \t\n for(uint i=1;i<256;i++)\n { \n Prec[i][0]=0;\n Prec[i][1]=0;\n \n for(uint j=0;j<8;j++)\n {\n \tif( (i&(1<=0.8.19 <0.9.0;\n\n\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\n\n\n\nlibrary FCL_ecdsa {\n // Set parameters for curve sec256r1.public\n //curve order (number of points)\n uint256 constant n = FCL_Elliptic_ZZ.n;\n \n /**\n * @dev ECDSA verification, given , signature, and public key.\n */\n\n /**\n * @dev ECDSA verification, given , signature, and public key, no calldata version\n */\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\n\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return false;\n }\n \n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\n return false;\n }\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\n uint256 x1;\n\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\n\n x1= addmod(x1, n-r,n );\n \n return x1 == 0;\n }\n\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\n {\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return address(0);\n }\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\n\n uint256 Qx;\n uint256 Qy;\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\n\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\n }\n\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\n internal view\n returns (bool)\n {\n \n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 X;\n\n //Shamir 8 dimensions\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\n\n X= addmod(X, n-r,n );\n\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\n internal view\n returns (bool)\n {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 X;\n\n //Shamir 8 dimensions\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\n\n X= addmod(X, n-r,n );\n\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n}\n" + }, + "FreshCryptoLib/FCL_elliptic.sol": { + "content": "//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n// |__/|_|\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_elliptic.sol\n///*\n///*\n///* DESCRIPTION: modified XYZZ system coordinates for EVM elliptic point multiplication\n///* optimization\n///*\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\nlibrary FCL_Elliptic_ZZ {\n // Set parameters for curve sec256r1.\n\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\n //curve prime field modulus\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n //short weierstrass first coefficient\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\n //short weierstrass second coefficient\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\n //generating point affine coordinates\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\n //curve order (number of points)\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\n /* -2 mod n constant, used to speed up inversion*/\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\n\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n //P+1 div 4\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\n //arbitrary constant to express no quadratic residuosity\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n\n /**\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\n */\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\n assembly {\n let pointer := mload(0x40)\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(pointer, 0x20)\n mstore(add(pointer, 0x20), 0x20)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base, exponent and modulus\n mstore(add(pointer, 0x60), u)\n mstore(add(pointer, 0x80), minus_2modn)\n mstore(add(pointer, 0xa0), n)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\n result := mload(pointer)\n }\n }\n /**\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\n */\n\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\n assembly {\n let pointer := mload(0x40)\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(pointer, 0x20)\n mstore(add(pointer, 0x20), 0x20)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base, exponent and modulus\n mstore(add(pointer, 0x60), u)\n mstore(add(pointer, 0x80), minus_2)\n mstore(add(pointer, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\n result := mload(pointer)\n }\n }\n\n //Coron projective shuffling, take as input alpha as blinding factor\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\n {\n \n uint256 alpha2=mulmod(alpha,alpha,p);\n \n x3=mulmod(alpha2, x,p); //alpha^-2.x\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\n\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\n \n return (x3, y3, zz3, zzz3);\n }\n\n\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\n {\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\n u2=addmod(u2, p-u1, p);// P = U2-U1\n x1=mulmod(u2, u2, p);//PP\n x2=mulmod(x1, u2, p);//PPP\n \n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\n\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\n\n return (x3, y3, zz3, zzz3);\n }\n\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\n/// @param self The integer of which to find the modular inverse\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\n\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\n assembly (\"memory-safe\") {\n // load the free memory pointer value\n let pointer := mload(0x40)\n\n // Define length of base (Bsize)\n mstore(pointer, 0x20)\n // Define the exponent size (Esize)\n mstore(add(pointer, 0x20), 0x20)\n // Define the modulus size (Msize)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base (B)\n mstore(add(pointer, 0x60), self)\n // Define the exponent (E)\n mstore(add(pointer, 0x80), pp1div4)\n // We save the point of the last argument, it will be override by the result\n // of the precompile call in order to avoid paying for the memory expansion properly\n let _result := add(pointer, 0xa0)\n // Define the modulus (M)\n mstore(_result, p)\n\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\n if iszero(\n staticcall(\n not(0), // amount of gas to send\n MODEXP_PRECOMPILE, // target\n pointer, // argsOffset\n 0xc0, // argsSize (6 * 32 bytes)\n _result, // retOffset (we override M to avoid paying for the memory expansion)\n 0x20 // retSize (32 bytes)\n )\n ) { revert(0, 0) }\n\n result := mload(_result)\n// result :=addmod(result,0,p)\n }\n if(mulmod(result,result,p)!=self){\n result=_NOTSQUARE;\n }\n \n return result;\n}\n /**\n * /* @dev Convert from affine rep to XYZZ rep\n */\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\n unchecked {\n P[2] = 1; //ZZ\n P[3] = 1; //ZZZ\n P[0] = x0;\n P[1] = y0;\n }\n }\n\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \n\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\n\n y=SqrtMod(y2);\n if(y==_NOTSQUARE){\n return _NOTONCURVE;\n }\n if((y&1)!=(parity&1)){\n y=p-y;\n }\n }\n\n /**\n * /* @dev Convert from XYZZ rep to affine rep\n */\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\n y1 = mulmod(y, zzzInv, p); //Y/zzz\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\n zzzInv = mulmod(_b, _b, p); //1/zz\n x1 = mulmod(x, zzzInv, p); //X/zz\n }\n\n /**\n * /* @dev Sutherland2008 doubling\n */\n /* The \"dbl-2008-s-1\" doubling formulas */\n\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\n internal\n pure\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\n {\n unchecked {\n assembly {\n P0 := mulmod(2, y, p) //U = 2*Y1\n P2 := mulmod(P0, P0, p) // V=U^2\n P3 := mulmod(x, P2, p) // S = X1*V\n P1 := mulmod(P0, P2, p) // W=UV\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\n }\n }\n return (P0, P1, P2, P3);\n }\n\n /**\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\n */\n\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\n internal\n pure\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\n {\n unchecked {\n if (y1 == 0) {\n return (x2, y2, 1, 1);\n }\n\n assembly {\n y1 := sub(p, y1)\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\n P0 := mulmod(x2, x2, p) //PP = P^2\n P1 := mulmod(P0, x2, p) //PPP = P*PP\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\n }\n //end assembly\n } //end unchecked\n return (P0, P1, P2, P3);\n }\n\n /**\n * @dev Return the zero curve in XYZZ coordinates.\n */\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\n return (0, 0, 0, 0);\n }\n /**\n * @dev Check if point is the neutral of the curve\n */\n\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\n return y0 == 0;\n }\n /**\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\n */\n\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\n return (0, 0);\n }\n\n /**\n * @dev Check if the curve is the zero curve in affine rep.\n */\n // uint256 x, uint256 y)\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\n return (y == 0);\n }\n\n /**\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\n */\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\n return false;\n }\n unchecked {\n uint256 LHS = mulmod(y, y, p); // y^2\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\n\n return LHS == RHS;\n }\n }\n\n /**\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\n */\n\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\n uint256 zz0;\n uint256 zzz0;\n\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\n if((x0==x1)&&(y0==y1)) {\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\n }\n else{\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\n }\n\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\n }\n\n /**\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\n * Returns only x for ECDSA use \n * */\n function ecZZ_mulmuladd_S_asm(\n uint256 Q0,\n uint256 Q1, //affine rep for input point Q\n uint256 scalar_u,\n uint256 scalar_v\n ) internal view returns (uint256 X) {\n uint256 zz;\n uint256 zzz;\n uint256 Y;\n uint256 index = 255;\n uint256 H0;\n uint256 H1;\n\n unchecked {\n if (scalar_u == 0 && scalar_v == 0) return 0;\n\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \n if((H0==0)&&(H1==0))//handling Q=-G\n {\n scalar_u=addmod(scalar_u, n-scalar_v, n);\n scalar_v=0;\n if (scalar_u == 0 && scalar_v == 0) return 0;\n }\n assembly {\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\n index := sub(index, 1)\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n } {}\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if eq(zz, 1) {\n X := gx\n Y := gy\n }\n if eq(zz, 2) {\n X := Q0\n Y := Q1\n }\n if eq(zz, 3) {\n X := H0\n Y := H1\n }\n\n index := sub(index, 1)\n zz := 1\n zzz := 1\n\n for {} gt(minus_1, index) { index := sub(index, 1) } {\n // inlined EcZZ_Dbl\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n {\n //value of dibit\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if iszero(T4) {\n Y := sub(p, Y) //restore the -Y inversion\n continue\n } // if T4!=0\n\n if eq(T4, 1) {\n T1 := gx\n T2 := gy\n }\n if eq(T4, 2) {\n T1 := Q0\n T2 := Q1\n }\n if eq(T4, 3) {\n T1 := H0\n T2 := H1\n }\n if iszero(zz) {\n X := T1\n Y := T2\n zz := 1\n zzz := 1\n continue\n }\n // inlined EcZZ_AddN\n\n //T3:=sub(p, Y)\n //T3:=Y\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\n\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\n //todo : construct edge vector case\n if iszero(y2) {\n if iszero(T2) {\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n T4 := mulmod(T2, T2, p) //PP\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\n zz := mulmod(zz, T4, p)\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\n let TT2 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\n\n X := T4\n }\n } //end loop\n let T := mload(0x40)\n mstore(add(T, 0x60), zz)\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n //Y:=mulmod(Y,zzz,p)//Y/zzz\n //zz :=mulmod(zz, mload(T),p) //1/z\n //zz:= mulmod(zz,zz,p) //1/zz\n X := mulmod(X, mload(T), p) //X/zz\n } //end assembly\n } //end unchecked\n\n return X;\n }\n\n\n /**\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\n * Returns affine representation of point (normalized) \n * */\n function ecZZ_mulmuladd(\n uint256 Q0,\n uint256 Q1, //affine rep for input point Q\n uint256 scalar_u,\n uint256 scalar_v\n ) internal view returns (uint256 X, uint256 Y) {\n uint256 zz;\n uint256 zzz;\n uint256 index = 255;\n uint256[6] memory T;\n uint256[2] memory H;\n \n unchecked {\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\n\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\n\n assembly {\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\n index := sub(index, 1)\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n } {}\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if eq(zz, 1) {\n X := gx\n Y := gy\n }\n if eq(zz, 2) {\n X := Q0\n Y := Q1\n }\n if eq(zz, 3) {\n Y := mload(add(H,32))\n X := mload(H)\n }\n\n index := sub(index, 1)\n zz := 1\n zzz := 1\n\n for {} gt(minus_1, index) { index := sub(index, 1) } {\n // inlined EcZZ_Dbl\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n {\n //value of dibit\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if iszero(T4) {\n Y := sub(p, Y) //restore the -Y inversion\n continue\n } // if T4!=0\n\n if eq(T4, 1) {\n T1 := gx\n T2 := gy\n }\n if eq(T4, 2) {\n T1 := Q0\n T2 := Q1\n }\n if eq(T4, 3) {\n T1 := mload(H)\n T2 := mload(add(H,32))\n }\n if iszero(zz) {\n X := T1\n Y := T2\n zz := 1\n zzz := 1\n continue\n }\n // inlined EcZZ_AddN\n\n //T3:=sub(p, Y)\n //T3:=Y\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\n\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\n //todo : construct edge vector case\n if iszero(y2) {\n if iszero(T2) {\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n T4 := mulmod(T2, T2, p) //PP\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\n zz := mulmod(zz, T4, p)\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\n let TT2 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\n\n X := T4\n }\n } //end loop\n mstore(add(T, 0x60), zzz)\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n Y:=mulmod(Y,mload(T),p)//Y/zzz\n zz :=mulmod(zz, mload(T),p) //1/z\n zz:= mulmod(zz,zz,p) //1/zz\n X := mulmod(X, zz, p) //X/zz\n } //end assembly\n } //end unchecked\n\n return (X,Y);\n }\n\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\n //contract at given address dataPointer\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\n // the external tool to generate tables from public key is in the /sage directory\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\n internal view\n returns (uint256 X /*, uint Y*/ )\n {\n unchecked {\n uint256 zz; // third and coordinates of the point\n\n uint256[6] memory T;\n zz = 256; //start index\n\n while (T[0] == 0) {\n zz = zz - 1;\n //tbd case of msb octobit is null\n T[0] = 64\n * (\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\n );\n }\n assembly {\n extcodecopy(dataPointer, T, mload(T), 64)\n let index := sub(zz, 1)\n X := mload(T)\n let Y := mload(add(T, 32))\n let zzz := 1\n zz := 1\n\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\n for {} gt(index, 191) { index := add(index, 191) } {\n //inline Double\n {\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(TT1, TT1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n let T1 := mulmod(TT1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n /* compute element to access in precomputed table */\n }\n {\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\n let index2 := sub(index, 64)\n let T3 :=\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\n let index3 := sub(index2, 64)\n let T2 :=\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\n index := sub(index3, 64)\n let T1 :=\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\n\n //tbd: check validity of formulae with (0,1) to remove conditional jump\n if iszero(T1) {\n Y := sub(p, Y)\n\n continue\n }\n extcodecopy(dataPointer, T, T1, 64)\n }\n\n {\n /* Access to precomputed table using extcodecopy hack */\n\n // inlined EcZZ_AddN\n if iszero(zz) {\n X := mload(T)\n Y := mload(add(T, 32))\n zz := 1\n zzz := 1\n\n continue\n }\n\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\n\n //special case ecAdd(P,P)=EcDbl\n if iszero(y2) {\n if iszero(T2) {\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n let T4 := mulmod(T2, T2, p)\n let T1 := mulmod(T4, T2, p) //\n zz := mulmod(zz, T4, p)\n //zzz3=V*ZZ1\n zzz := mulmod(zzz, T1, p) // W=UV/\n let zz1 := mulmod(X, T4, p)\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\n }\n } //end loop\n mstore(add(T, 0x60), zz)\n\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n zz := mload(T)\n X := mulmod(X, zz, p) //X/zz\n }\n } //end unchecked\n }\n\n \n\n // improving the extcodecopy trick : append array at end of contract\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\n internal view\n returns (uint256 X /*, uint Y*/ )\n {\n uint256 zz; // third and coordinates of the point\n\n uint256[6] memory T;\n zz = 256; //start index\n\n unchecked {\n while (T[0] == 0) {\n zz = zz - 1;\n //tbd case of msb octobit is null\n T[0] = 64\n * (\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\n );\n }\n assembly {\n codecopy(T, add(mload(T), dataPointer), 64)\n X := mload(T)\n let Y := mload(add(T, 32))\n let zzz := 1\n zz := 1\n\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n /* compute element to access in precomputed table */\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\n index := sub(index, 64)\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\n index := sub(index, 64)\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\n index := sub(index, 64)\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\n //index:=add(index,192), restore index, interleaved with loop\n\n //tbd: check validity of formulae with (0,1) to remove conditional jump\n if iszero(T4) {\n Y := sub(p, Y)\n\n continue\n }\n {\n /* Access to precomputed table using extcodecopy hack */\n codecopy(T, add(T4, dataPointer), 64)\n\n // inlined EcZZ_AddN\n\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\n T4 := mulmod(T2, T2, p)\n T1 := mulmod(T4, T2, p)\n T2 := mulmod(zz, T4, p) // W=UV\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\n let zz1 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\n zz := T2\n X := T4\n }\n } //end loop\n mstore(add(T, 0x60), zz)\n\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n zz := mload(T)\n X := mulmod(X, zz, p) //X/zz\n }\n } //end unchecked\n }\n\n\n /**\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\n * generation of contract bytecode for precomputations is done using sagemath code\n * (see sage directory, WebAuthn_precompute.sage)\n */\n\n /**\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\n * generation of contract bytecode for precomputations is done using sagemath code\n * (see sage directory, WebAuthn_precompute.sage)\n */\n\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\n internal view\n returns (bool)\n {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via bytecode assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_nModInv(s);\n uint256 X;\n\n //Shamir 8 dimensions\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\n\n assembly {\n X := addmod(X, sub(n, r), n)\n }\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n\n\n} //EOF\n" + }, + "FreshCryptoLib/FCL_Webauthn.sol": { + "content": "//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_elliptic.sol\n///*\n///*\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\nimport {Base64Url} from \"./utils/Base64Url.sol\";\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\nimport {FCL_ecdsa} from \"./FCL_ecdsa.sol\";\n\nimport {FCL_ecdsa_utils} from \"./FCL_ecdsa_utils.sol\";\n\nlibrary FCL_WebAuthn {\n error InvalidAuthenticatorData();\n error InvalidClientData();\n error InvalidSignature();\n\n function WebAuthn_format(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata // rs\n ) internal pure returns (bytes32 result) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n {\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\n revert InvalidAuthenticatorData();\n }\n // Verify that clientData commits to the expected client challenge\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\n bytes memory challengeExtracted = new bytes(\n bytes(challengeEncoded).length\n );\n\n assembly {\n calldatacopy(\n add(challengeExtracted, 32),\n add(clientData.offset, clientChallengeDataOffset),\n mload(challengeExtracted)\n )\n }\n\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\n assembly {\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\n }\n\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\n revert InvalidClientData();\n }\n } //avoid stack full\n\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\n\n assembly {\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\n }\n\n bytes32 more = sha256(clientData);\n assembly {\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\n }\n\n return sha256(verifyData);\n }\n\n function checkSignature (\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256[2] calldata Q\n ) internal view returns (bool) {\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\n }\n\n function checkSignature (\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256 Qx,\n uint256 Qy\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\n\n return result;\n }\n\n function checkSignature_prec(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n address dataPointer\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\n\n return result;\n }\n\n //beware that this implementation will not be compliant with EOF\n function checkSignature_hackmem(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256 dataPointer\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\n\n return result;\n }\n}\n" + }, + "FreshCryptoLib/utils/Base64Url.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\n/**\n * @dev Encode (without '=' padding) \n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\n */\nlibrary Base64Url {\n /**\n * @dev Base64Url Encoding Table\n */\n string internal constant ENCODING_TABLE =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\n function encode(bytes memory data) internal pure returns (string memory) {\n if (data.length == 0) return \"\";\n\n // Load the table into memory\n string memory table = ENCODING_TABLE;\n\n string memory result = new string(4 * ((data.length + 2) / 3));\n\n // @solidity memory-safe-assembly\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let dataPtr := data\n let endPtr := add(data, mload(data))\n } lt(dataPtr, endPtr) {\n\n } {\n dataPtr := add(dataPtr, 3)\n let input := mload(dataPtr)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n resultPtr := add(resultPtr, 1)\n }\n\n // Remove the padding adjustment logic\n switch mod(mload(data), 3)\n case 1 {\n // Adjust for the last byte of data\n resultPtr := sub(resultPtr, 2)\n }\n case 2 {\n // Adjust for the last two bytes of data\n resultPtr := sub(resultPtr, 1)\n }\n \n // Set the correct length of the result string\n mstore(result, sub(resultPtr, add(result, 32)))\n }\n\n return result; \n }\n}\n" + }, + "solady/src/utils/LibClone.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Minimal proxy library.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)\n/// @author Minimal proxy by 0age (https://github.com/0age)\n/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\n///\n/// @dev Minimal proxy:\n/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,\n/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,\n/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.\n///\n/// @dev Minimal proxy (PUSH0 variant):\n/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.\n/// It is optimized first for minimal runtime gas, then for minimal bytecode.\n/// The PUSH0 clone functions are intentionally postfixed with a jarring \"_PUSH0\" as\n/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.\n/// Please use with caution.\n///\n/// @dev Clones with immutable args (CWIA):\n/// The implementation of CWIA here implements a `receive()` method that emits the\n/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,\n/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards\n/// composability. The minimal proxy implementation does not offer this feature.\nlibrary LibClone {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Unable to deploy the clone.\n error DeploymentFailed();\n\n /// @dev The salt must start with either the zero address or the caller.\n error SaltDoesNotStartWithCaller();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MINIMAL PROXY OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a clone of `implementation`.\n function clone(address implementation) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * --------------------------------------------------------------------------+\n * CREATION (9 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * --------------------------------------------------------------------------|\n * RUNTIME (44 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * |\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | |\n * 3d | RETURNDATASIZE | 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 0 0 | |\n * |\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |\n * 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |\n * |\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\n * |\n * 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\n * |\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * --------------------------------------------------------------------------+\n */\n\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n instance := create(0, 0x0c, 0x35)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation` with `salt`.\n function cloneDeterministic(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n instance := create2(0, 0x0c, 0x35, salt)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Returns the initialization code hash of the clone of `implementation`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n hash := keccak256(0x0c, 0x35)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Returns the address of the deterministic clone of `implementation`,\n /// with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)\n internal\n pure\n returns (address predicted)\n {\n bytes32 hash = initCodeHash(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a PUSH0 clone of `implementation`.\n function clone_PUSH0(address implementation) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * --------------------------------------------------------------------------+\n * CREATION (9 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 5f | PUSH0 | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 5f | PUSH0 | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * --------------------------------------------------------------------------|\n * RUNTIME (45 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * |\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n * 5f | PUSH0 | 0 | |\n * 5f | PUSH0 | 0 0 | |\n * |\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 | |\n * 5f | PUSH0 | 0 cds 0 0 | |\n * 5f | PUSH0 | 0 0 cds 0 0 | |\n * 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |\n * 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success | [0..cds): calldata |\n * |\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success | [0..cds): calldata |\n * 5f | PUSH0 | 0 rds success | [0..cds): calldata |\n * 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success | [0..rds): returndata |\n * |\n * 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |\n * 57 | JUMPI | | [0..rds): returndata |\n * |\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | [0..rds): returndata |\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * --------------------------------------------------------------------------+\n */\n\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n instance := create(0, 0x0e, 0x36)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\n function cloneDeterministic_PUSH0(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n instance := create2(0, 0x0e, 0x36, salt)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n hash := keccak256(0x0e, 0x36)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,\n /// with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress_PUSH0(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHash_PUSH0(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CLONES WITH IMMUTABLE ARGS OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a minimal proxy with `implementation`,\n /// using immutable arguments encoded in `data`.\n ///\n /// Note: This implementation of CWIA differs from the original implementation.\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\n function clone(address implementation, bytes memory data) internal returns (address instance) {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n // The `creationSize` is `extraLength + 108`\n // The `runSize` is `creationSize - 10`.\n\n /**\n * ---------------------------------------------------------------------------------------------------+\n * CREATION (10 bytes) |\n * ---------------------------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------------------------|\n * 61 runSize | PUSH2 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * ---------------------------------------------------------------------------------------------------|\n * RUNTIME (98 bytes + extraLength) |\n * ---------------------------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------------------------|\n * |\n * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 60 0x2c | PUSH1 0x2c | 0x2c cds | |\n * 57 | JUMPI | | |\n * 34 | CALLVALUE | cv | |\n * 3d | RETURNDATASIZE | 0 cv | |\n * 52 | MSTORE | | [0..0x20): callvalue |\n * 7f sig | PUSH32 0x9e.. | sig | [0..0x20): callvalue |\n * 59 | MSIZE | 0x20 sig | [0..0x20): callvalue |\n * 3d | RETURNDATASIZE | 0 0x20 sig | [0..0x20): callvalue |\n * a1 | LOG1 | | [0..0x20): callvalue |\n * 00 | STOP | | [0..0x20): callvalue |\n * 5b | JUMPDEST | | |\n * |\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 3d | RETURNDATASIZE | 0 cds | |\n * 3d | RETURNDATASIZE | 0 0 cds | |\n * 37 | CALLDATACOPY | | [0..cds): calldata |\n * |\n * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata |\n * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata |\n * |\n * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata |\n * 60 0x62 | PUSH1 0x62 | 0x62 e e 0 0 0 0 | [0..cds): calldata |\n * 36 | CALLDATASIZE | cds 0x62 e e 0 0 0 0 | [0..cds): calldata |\n * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * |\n * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * |\n * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\n * |\n * 60 0x60 | PUSH1 0x60 | 0x60 success 0 rds | [0..rds): returndata |\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\n * |\n * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * ---------------------------------------------------------------------------------------------------+\n */\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\n // The actual EVM limit may be smaller and may change over time.\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Create the instance.\n instance := create(0, sub(data, 0x4c), add(extraLength, 0x6c))\n\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation`,\n /// using immutable arguments encoded in `data`, with `salt`.\n ///\n /// Note: This implementation of CWIA differs from the original implementation.\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\n function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)\n internal\n returns (address instance)\n {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\n // The actual EVM limit may be smaller and may change over time.\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Create the instance.\n instance := create2(0, sub(data, 0x4c), add(extraLength, 0x6c), salt)\n\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Returns the initialization code hash of the clone of `implementation`\n /// using immutable arguments encoded in `data`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash(address implementation, bytes memory data)\n internal\n pure\n returns (bytes32 hash)\n {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.\n // The actual EVM limit may be smaller and may change over time.\n returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n sub(data, 0x5a),\n or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Compute and store the bytecode hash.\n hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Returns the address of the deterministic clone of\n /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(\n address implementation,\n bytes memory data,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHash(implementation, data);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* OTHER OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns the address when a contract with initialization code hash,\n /// `hash`, is deployed with `salt`, by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)\n internal\n pure\n returns (address predicted)\n {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, hash)\n mstore(0x01, shl(96, deployer))\n mstore(0x15, salt)\n predicted := keccak256(0x00, 0x55)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x35, 0)\n }\n }\n\n /// @dev Reverts if `salt` does not start with either the zero address or the caller.\n function checkStartsWithCaller(bytes32 salt) internal view {\n /// @solidity memory-safe-assembly\n assembly {\n // If the salt does not start with the zero address or the caller.\n if iszero(or(iszero(shr(96, salt)), eq(caller(), shr(96, salt)))) {\n // Store the function selector of `SaltDoesNotStartWithCaller()`.\n mstore(0x00, 0x2f634836)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n }\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/optimism_production/.chainId b/deployments/optimism_production/.chainId new file mode 100644 index 0000000..9a03714 --- /dev/null +++ b/deployments/optimism_production/.chainId @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/deployments/optimism_production/P256Signer.json b/deployments/optimism_production/P256Signer.json new file mode 100644 index 0000000..713adaf --- /dev/null +++ b/deployments/optimism_production/P256Signer.json @@ -0,0 +1,275 @@ +{ + "address": "0x93ae54DAE3A266d2F7197d118e1B3A89429ba55F", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHash", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "y_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "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": [ + { + "internalType": "bytes", + "name": "_hash", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "x", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "y", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xc676adb06e7d68112d547ef4ef46c67ba914df4b0a1a1ad047b4e295a2ee0e31", + "receipt": { + "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", + "from": "0x61f2ad863873d2466B64cef9cdC65361F98A65D3", + "contractAddress": null, + "transactionIndex": 18, + "gasUsed": "1848511", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x0232b3a7a940e4350ac1790a090a35cee76823628feb04f81319a2a4d934122c", + "transactionHash": "0xc676adb06e7d68112d547ef4ef46c67ba914df4b0a1a1ad047b4e295a2ee0e31", + "logs": [], + "blockNumber": 117974146, + "cumulativeGasUsed": "3552340", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "01c9a206ce5ca6951fd356b6a1b5a7d7", + "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAuthenticatorData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidClientData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidHash\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y_\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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\":[{\"internalType\":\"bytes\",\"name\":\"_hash\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"isValidSignature\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"x\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"y\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract is the implementation. It is meant to be used through proxy clone.\",\"kind\":\"dev\",\"methods\":{\"initialize(uint256,uint256)\":{\"details\":\"This function is only callable once and needs to be called immediately after deployment by the factory in the same transaction.\",\"params\":{\"x_\":\"The x coordinate of the public key\",\"y_\":\"The y coordinate of the public key\"}},\"isValidSignature(bytes,bytes)\":{\"details\":\"This is the old version of the function of EIP-1271 using bytes memory instead of bytes32\",\"params\":{\"_hash\":\"The hash of the data signed\",\"_signature\":\"The signature\"},\"returns\":{\"_0\":\"The EIP-1271 magic value\"}},\"isValidSignature(bytes32,bytes)\":{\"params\":{\"_hash\":\"The hash of the data signed\",\"_signature\":\"The signature\"},\"returns\":{\"_0\":\"The EIP-1271 magic value\"}}},\"title\":\"P256Signer\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInitialized()\":[{\"notice\":\"Error message when the contract is already initialized\"}],\"InvalidHash()\":[{\"notice\":\"Error message when the hash is invalid\"}],\"InvalidSignature()\":[{\"notice\":\"Error message when the signature is invalid\"}]},\"kind\":\"user\",\"methods\":{\"initialized()\":{\"notice\":\"Whether the contract has been initialized\"},\"isValidSignature(bytes,bytes)\":{\"notice\":\"Verifies that the signer is the owner of the secp256r1 public key.\"},\"isValidSignature(bytes32,bytes)\":{\"notice\":\"Verifies that the signer is the owner of the secp256r1 public key.\"},\"x()\":{\"notice\":\"The x coordinate of the secp256r1 public key\"},\"y()\":{\"notice\":\"The y coordinate of the secp256r1 public key\"}},\"notice\":\"A contract used to verify ECDSA signatures over secp256r1 through EIP-1271 of Webauthn payloads.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/P256Signer.sol\":\"P256Signer\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"FreshCryptoLib/FCL_Webauthn.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_elliptic.sol\\n///*\\n///*\\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\nimport {FCL_ecdsa} from \\\"./FCL_ecdsa.sol\\\";\\n\\nimport {FCL_ecdsa_utils} from \\\"./FCL_ecdsa_utils.sol\\\";\\n\\nlibrary FCL_WebAuthn {\\n error InvalidAuthenticatorData();\\n error InvalidClientData();\\n error InvalidSignature();\\n\\n function WebAuthn_format(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata // rs\\n ) internal pure returns (bytes32 result) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n {\\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\\n revert InvalidAuthenticatorData();\\n }\\n // Verify that clientData commits to the expected client challenge\\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\\n bytes memory challengeExtracted = new bytes(\\n bytes(challengeEncoded).length\\n );\\n\\n assembly {\\n calldatacopy(\\n add(challengeExtracted, 32),\\n add(clientData.offset, clientChallengeDataOffset),\\n mload(challengeExtracted)\\n )\\n }\\n\\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\\n assembly {\\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\\n }\\n\\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\\n revert InvalidClientData();\\n }\\n } //avoid stack full\\n\\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\\n\\n assembly {\\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\\n }\\n\\n bytes32 more = sha256(clientData);\\n assembly {\\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\\n }\\n\\n return sha256(verifyData);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256[2] calldata Q\\n ) internal view returns (bool) {\\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 Qx,\\n uint256 Qy\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\\n\\n return result;\\n }\\n\\n function checkSignature_prec(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n address dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\\n\\n return result;\\n }\\n\\n //beware that this implementation will not be compliant with EOF\\n function checkSignature_hackmem(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc2811ef6e17ea1d5509a3d3f7d5af5e56583347b36093d05530425d7c1316dd6\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n /**\\n * @dev ECDSA verification, given , signature, and public key, no calldata version\\n */\\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\\n\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n \\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n\\n x1= addmod(x1, n-r,n );\\n \\n return x1 == 0;\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n \\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n}\\n\",\"keccak256\":\"0x679d2e9a655cd7e156a0cfc24de0aca88d4e0b34a8e0dfe6a599f23af092f5a2\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa_utils.sol\":{\"content\":\"\\n//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa_utils {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n x1= addmod(x1, n-r,n );\\n \\n \\n return x1 == 0;\\n }\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\n return ecdsa_verify(message, rs, Q[0], Q[1]);\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n\\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\\n //K is nonce, kpriv is private key\\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\\n {\\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \\n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n //ecdsa key derivation\\n //kpriv is private key return (x,y) coordinates of associated Pubkey\\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\\n {\\n \\n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\\n \\n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\\n {\\n y=FCL_Elliptic_ZZ.p-y;\\n } \\n\\n }\\n \\n //precomputations for 8 dimensional trick\\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\\n {\\n \\n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\\n \\n //the trivial private keys 1 and -1 are forbidden\\n if(Qx==FCL_Elliptic_ZZ.gx)\\n {\\n revert();\\n }\\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\\n \\n Pow64_PQ[4][0]=Qx;\\n Pow64_PQ[4][1]=Qy;\\n \\n /* raise to multiplication by 64 by 6 consecutive doubling*/\\n for(uint j=1;j<4;j++){\\n uint256 x;\\n uint256 y;\\n uint256 zz;\\n uint256 zzz;\\n \\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\\n \\t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\\n \\t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n\\n \\tfor(uint i=0;i<63;i++){\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t}\\n }\\n \\n /* neutral point */\\n Prec[0][0]=0;\\n Prec[0][1]=0;\\n \\n \\t\\n for(uint i=1;i<256;i++)\\n { \\n Prec[i][0]=0;\\n Prec[i][1]=0;\\n \\n for(uint j=0;j<8;j++)\\n {\\n \\tif( (i&(1<=0.8.19 <0.9.0;\\n\\nlibrary FCL_Elliptic_ZZ {\\n // Set parameters for curve sec256r1.\\n\\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\\n //curve prime field modulus\\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n //short weierstrass first coefficient\\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n //short weierstrass second coefficient\\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n //generating point affine coordinates\\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n //curve order (number of points)\\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\\n /* -2 mod n constant, used to speed up inversion*/\\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\\n\\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n //P+1 div 4\\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\\n //arbitrary constant to express no quadratic residuosity\\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n /**\\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\\n */\\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2modn)\\n mstore(add(pointer, 0xa0), n)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n /**\\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\\n */\\n\\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2)\\n mstore(add(pointer, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n\\n //Coron projective shuffling, take as input alpha as blinding factor\\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n \\n uint256 alpha2=mulmod(alpha,alpha,p);\\n \\n x3=mulmod(alpha2, x,p); //alpha^-2.x\\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\\n\\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\\n \\n return (x3, y3, zz3, zzz3);\\n }\\n\\n\\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\\n u2=addmod(u2, p-u1, p);// P = U2-U1\\n x1=mulmod(u2, u2, p);//PP\\n x2=mulmod(x1, u2, p);//PPP\\n \\n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \\n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\\n\\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \\n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\\n\\n return (x3, y3, zz3, zzz3);\\n }\\n\\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\\n/// @param self The integer of which to find the modular inverse\\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\\n\\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\\n assembly (\\\"memory-safe\\\") {\\n // load the free memory pointer value\\n let pointer := mload(0x40)\\n\\n // Define length of base (Bsize)\\n mstore(pointer, 0x20)\\n // Define the exponent size (Esize)\\n mstore(add(pointer, 0x20), 0x20)\\n // Define the modulus size (Msize)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base (B)\\n mstore(add(pointer, 0x60), self)\\n // Define the exponent (E)\\n mstore(add(pointer, 0x80), pp1div4)\\n // We save the point of the last argument, it will be override by the result\\n // of the precompile call in order to avoid paying for the memory expansion properly\\n let _result := add(pointer, 0xa0)\\n // Define the modulus (M)\\n mstore(_result, p)\\n\\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\\n if iszero(\\n staticcall(\\n not(0), // amount of gas to send\\n MODEXP_PRECOMPILE, // target\\n pointer, // argsOffset\\n 0xc0, // argsSize (6 * 32 bytes)\\n _result, // retOffset (we override M to avoid paying for the memory expansion)\\n 0x20 // retSize (32 bytes)\\n )\\n ) { revert(0, 0) }\\n\\n result := mload(_result)\\n// result :=addmod(result,0,p)\\n }\\n if(mulmod(result,result,p)!=self){\\n result=_NOTSQUARE;\\n }\\n \\n return result;\\n}\\n /**\\n * /* @dev Convert from affine rep to XYZZ rep\\n */\\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\\n unchecked {\\n P[2] = 1; //ZZ\\n P[3] = 1; //ZZZ\\n P[0] = x0;\\n P[1] = y0;\\n }\\n }\\n\\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \\n\\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\\n\\n y=SqrtMod(y2);\\n if(y==_NOTSQUARE){\\n return _NOTONCURVE;\\n }\\n if((y&1)!=(parity&1)){\\n y=p-y;\\n }\\n }\\n\\n /**\\n * /* @dev Convert from XYZZ rep to affine rep\\n */\\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\\n y1 = mulmod(y, zzzInv, p); //Y/zzz\\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\\n zzzInv = mulmod(_b, _b, p); //1/zz\\n x1 = mulmod(x, zzzInv, p); //X/zz\\n }\\n\\n /**\\n * /* @dev Sutherland2008 doubling\\n */\\n /* The \\\"dbl-2008-s-1\\\" doubling formulas */\\n\\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n assembly {\\n P0 := mulmod(2, y, p) //U = 2*Y1\\n P2 := mulmod(P0, P0, p) // V=U^2\\n P3 := mulmod(x, P2, p) // S = X1*V\\n P1 := mulmod(P0, P2, p) // W=UV\\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\\n }\\n }\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\\n */\\n\\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n if (y1 == 0) {\\n return (x2, y2, 1, 1);\\n }\\n\\n assembly {\\n y1 := sub(p, y1)\\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\\n P0 := mulmod(x2, x2, p) //PP = P^2\\n P1 := mulmod(P0, x2, p) //PPP = P*PP\\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\\n }\\n //end assembly\\n } //end unchecked\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Return the zero curve in XYZZ coordinates.\\n */\\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\\n return (0, 0, 0, 0);\\n }\\n /**\\n * @dev Check if point is the neutral of the curve\\n */\\n\\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\\n return y0 == 0;\\n }\\n /**\\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\\n */\\n\\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\\n return (0, 0);\\n }\\n\\n /**\\n * @dev Check if the curve is the zero curve in affine rep.\\n */\\n // uint256 x, uint256 y)\\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\\n return (y == 0);\\n }\\n\\n /**\\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\\n */\\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\\n return false;\\n }\\n unchecked {\\n uint256 LHS = mulmod(y, y, p); // y^2\\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n\\n return LHS == RHS;\\n }\\n }\\n\\n /**\\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\\n */\\n\\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\\n uint256 zz0;\\n uint256 zzz0;\\n\\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\\n if((x0==x1)&&(y0==y1)) {\\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\\n }\\n else{\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\n }\\n\\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\\n }\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns only x for ECDSA use \\n * */\\n function ecZZ_mulmuladd_S_asm(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 Y;\\n uint256 index = 255;\\n uint256 H0;\\n uint256 H1;\\n\\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n\\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \\n if((H0==0)&&(H1==0))//handling Q=-G\\n {\\n scalar_u=addmod(scalar_u, n-scalar_v, n);\\n scalar_v=0;\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n }\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n X := H0\\n Y := H1\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := H0\\n T2 := H1\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n let T := mload(0x40)\\n mstore(add(T, 0x60), zz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n //Y:=mulmod(Y,zzz,p)//Y/zzz\\n //zz :=mulmod(zz, mload(T),p) //1/z\\n //zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, mload(T), p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return X;\\n }\\n\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns affine representation of point (normalized) \\n * */\\n function ecZZ_mulmuladd(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X, uint256 Y) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 index = 255;\\n uint256[6] memory T;\\n uint256[2] memory H;\\n \\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\\n\\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\\n\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n Y := mload(add(H,32))\\n X := mload(H)\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := mload(H)\\n T2 := mload(add(H,32))\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zzz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n Y:=mulmod(Y,mload(T),p)//Y/zzz\\n zz :=mulmod(zz, mload(T),p) //1/z\\n zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, zz, p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return (X,Y);\\n }\\n\\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\\n //contract at given address dataPointer\\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\\n // the external tool to generate tables from public key is in the /sage directory\\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n unchecked {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n extcodecopy(dataPointer, T, mload(T), 64)\\n let index := sub(zz, 1)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for {} gt(index, 191) { index := add(index, 191) } {\\n //inline Double\\n {\\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(TT1, TT1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n let T1 := mulmod(TT1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n }\\n {\\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n let index2 := sub(index, 64)\\n let T3 :=\\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\\n let index3 := sub(index2, 64)\\n let T2 :=\\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\\n index := sub(index3, 64)\\n let T1 :=\\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T1) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n extcodecopy(dataPointer, T, T1, 64)\\n }\\n\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n\\n // inlined EcZZ_AddN\\n if iszero(zz) {\\n X := mload(T)\\n Y := mload(add(T, 32))\\n zz := 1\\n zzz := 1\\n\\n continue\\n }\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n\\n //special case ecAdd(P,P)=EcDbl\\n if iszero(y2) {\\n if iszero(T2) {\\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n let T4 := mulmod(T2, T2, p)\\n let T1 := mulmod(T4, T2, p) //\\n zz := mulmod(zz, T4, p)\\n //zzz3=V*ZZ1\\n zzz := mulmod(zzz, T1, p) // W=UV/\\n let zz1 := mulmod(X, T4, p)\\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n \\n\\n // improving the extcodecopy trick : append array at end of contract\\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n unchecked {\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n codecopy(T, add(mload(T), dataPointer), 64)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n //index:=add(index,192), restore index, interleaved with loop\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T4) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n codecopy(T, add(T4, dataPointer), 64)\\n\\n // inlined EcZZ_AddN\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n T4 := mulmod(T2, T2, p)\\n T1 := mulmod(T4, T2, p)\\n T2 := mulmod(zz, T4, p) // W=UV\\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\\n let zz1 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\\n zz := T2\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n\\n\\n} //EOF\\n\",\"keccak256\":\"0x7f244805668cc589ae33f18c35c68738db25994c9befbb5d07f28a91fb03ba44\",\"license\":\"MIT\"},\"FreshCryptoLib/utils/Base64Url.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Encode (without '=' padding) \\n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\\n */\\nlibrary Base64Url {\\n /**\\n * @dev Base64Url Encoding Table\\n */\\n string internal constant ENCODING_TABLE =\\n \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\\\";\\n\\n function encode(bytes memory data) internal pure returns (string memory) {\\n if (data.length == 0) return \\\"\\\";\\n\\n // Load the table into memory\\n string memory table = ENCODING_TABLE;\\n\\n string memory result = new string(4 * ((data.length + 2) / 3));\\n\\n // @solidity memory-safe-assembly\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let dataPtr := data\\n let endPtr := add(data, mload(data))\\n } lt(dataPtr, endPtr) {\\n\\n } {\\n dataPtr := add(dataPtr, 3)\\n let input := mload(dataPtr)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n resultPtr := add(resultPtr, 1)\\n }\\n\\n // Remove the padding adjustment logic\\n switch mod(mload(data), 3)\\n case 1 {\\n // Adjust for the last byte of data\\n resultPtr := sub(resultPtr, 2)\\n }\\n case 2 {\\n // Adjust for the last two bytes of data\\n resultPtr := sub(resultPtr, 1)\\n }\\n \\n // Set the correct length of the result string\\n mstore(result, sub(resultPtr, add(result, 32)))\\n }\\n\\n return result; \\n }\\n}\\n\",\"keccak256\":\"0xc9d5fbb0ef9ff0756eb5aabe7a32b2bf0f8f3c533d4451dd5778fe77aee7f0c1\",\"license\":\"Apache-2.0\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title P256Signer\\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This contract is the implementation. It is meant to be used through\\n/// proxy clone.\\ncontract P256Signer {\\n /// @notice The EIP-1271 magic value\\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\\n\\n /// @notice The old EIP-1271 magic value\\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\\n\\n /// @notice Whether the contract has been initialized\\n bool public initialized;\\n\\n /// @notice The x coordinate of the secp256r1 public key\\n uint256 public x;\\n\\n /// @notice The y coordinate of the secp256r1 public key\\n uint256 public y;\\n\\n /// @notice Error message when the signature is invalid\\n error InvalidSignature();\\n\\n /// @notice Error message when the hash is invalid\\n error InvalidHash();\\n\\n /// @notice Error message when the contract is already initialized\\n error AlreadyInitialized();\\n\\n constructor() {\\n initialized = true;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(abi.encode(_hash), _signature);\\n return EIP1271_MAGICVALUE;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @dev This is the old version of the function of EIP-1271 using bytes\\n /// memory instead of bytes32\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\n }\\n\\n struct SignatureLayout {\\n bytes authenticatorData;\\n bytes clientData;\\n uint256 challengeOffset;\\n uint256[2] rs;\\n }\\n\\n /// @notice Validates the signature\\n /// @param data The data signed\\n /// @param _signature The signature\\n function _validate(bytes memory data, bytes calldata _signature) private view {\\n bytes32 _hash = keccak256(data);\\n SignatureLayout calldata signaturePointer;\\n // This code should precalculate the offsets of variables as defined in the layout\\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\\n assembly {\\n signaturePointer := _signature.offset\\n }\\n\\n bool valid = FCL_WebAuthn.checkSignature(\\n signaturePointer.authenticatorData,\\n 0x01,\\n signaturePointer.clientData,\\n _hash,\\n signaturePointer.challengeOffset,\\n signaturePointer.rs,\\n x,\\n y\\n );\\n\\n if (!valid) revert InvalidSignature();\\n }\\n\\n /// @dev This function is only callable once and needs to be called immediately\\n /// after deployment by the factory in the same transaction.\\n /// @param x_ The x coordinate of the public key\\n /// @param y_ The y coordinate of the public key\\n function initialize(uint256 x_, uint256 y_) external {\\n if (initialized) revert AlreadyInitialized();\\n initialized = true;\\n x = x_;\\n y = y_;\\n }\\n}\\n\",\"keccak256\":\"0xfc1b006adb6ace0364918015a1aa64439374f813383bcc71290f6b37b66641e5\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561206a8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cd8565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d53565b61017c565b61008060025481565b61012361011e366004611e3f565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e61565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e61565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ec6565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d24565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ef5565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f53565b67ffffffffffffffff8111156104a7576104a7611d24565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f66565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f76565b90508060208b018301526002826040516105499190611ef5565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f76565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f8f565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611ff560409139905060006003845160026107459190611f53565b61074f9190611fa2565b61075a906004611fdd565b67ffffffffffffffff81111561077257610772611d24565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff831480156108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611580565b909250905081158015610aea575080155b15610b5b577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a0898506000975088158015610b47575087155b15610b5b57600096505050505050506106ef565b600189841c16600189851c1660011b015b80610b8e5760018403935060018a851c1660018a861c1660011b019050610b6c565b50600189841c16600189851c1660011b01955060018603610bf0577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610bff578a96508993505b60038603610c0e578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114d0577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610ef957877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114c5565b60018103610f48577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f57578e93508d92505b60038103610f66578593508492505b89610f7f57509198506001975087965094506114c59050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8809089350806112be57836112be577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114c5565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610c1d565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61154b57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b600080808086611597578585935093505050611605565b846115a9578787935093505050611605565b85881480156115b757508487145b156115d8576115c9888860018061160e565b929a50909850925090506115f2565b6115e788886001808a8a611898565b929a50909850925090505b6115fe88888484611b5d565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b600080600080886000036118b757508492508391506001905080611b50565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b6b84611c12565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611ca157600080fd5b50813567ffffffffffffffff811115611cb957600080fd5b602083019150836020828501011115611cd157600080fd5b9250929050565b600080600060408486031215611ced57600080fd5b83359250602084013567ffffffffffffffff811115611d0b57600080fd5b611d1786828701611c8f565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d6857600080fd5b833567ffffffffffffffff80821115611d8057600080fd5b818601915086601f830112611d9457600080fd5b813581811115611da657611da6611d24565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dec57611dec611d24565b81604052828152896020848701011115611e0557600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e3257600080fd5b50611d1786828701611c8f565b60008060408385031215611e5257600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e9657600080fd5b83018035915067ffffffffffffffff821115611eb157600080fd5b602001915036819003821315611cd157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611f165760208186018101518583015201611efc565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f24565b8183823760009101908152919050565b600060208284031215611f8857600080fd5b5051919050565b818103818111156109da576109da611f24565b600082611fd8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f2456fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa2646970667358221220c618cb60ccea4d134580893ea1be714ea2f3ee81e84f2989f14e663d114ee00a64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cd8565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d53565b61017c565b61008060025481565b61012361011e366004611e3f565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e61565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e61565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ec6565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d24565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ef5565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f53565b67ffffffffffffffff8111156104a7576104a7611d24565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f66565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f76565b90508060208b018301526002826040516105499190611ef5565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f76565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f8f565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611ff560409139905060006003845160026107459190611f53565b61074f9190611fa2565b61075a906004611fdd565b67ffffffffffffffff81111561077257610772611d24565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff831480156108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611580565b909250905081158015610aea575080155b15610b5b577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a0898506000975088158015610b47575087155b15610b5b57600096505050505050506106ef565b600189841c16600189851c1660011b015b80610b8e5760018403935060018a851c1660018a861c1660011b019050610b6c565b50600189841c16600189851c1660011b01955060018603610bf0577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610bff578a96508993505b60038603610c0e578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114d0577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610ef957877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114c5565b60018103610f48577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f57578e93508d92505b60038103610f66578593508492505b89610f7f57509198506001975087965094506114c59050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8809089350806112be57836112be577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114c5565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610c1d565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61154b57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b600080808086611597578585935093505050611605565b846115a9578787935093505050611605565b85881480156115b757508487145b156115d8576115c9888860018061160e565b929a50909850925090506115f2565b6115e788886001808a8a611898565b929a50909850925090505b6115fe88888484611b5d565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b600080600080886000036118b757508492508391506001905080611b50565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b6b84611c12565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611ca157600080fd5b50813567ffffffffffffffff811115611cb957600080fd5b602083019150836020828501011115611cd157600080fd5b9250929050565b600080600060408486031215611ced57600080fd5b83359250602084013567ffffffffffffffff811115611d0b57600080fd5b611d1786828701611c8f565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d6857600080fd5b833567ffffffffffffffff80821115611d8057600080fd5b818601915086601f830112611d9457600080fd5b813581811115611da657611da6611d24565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dec57611dec611d24565b81604052828152896020848701011115611e0557600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e3257600080fd5b50611d1786828701611c8f565b60008060408385031215611e5257600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e9657600080fd5b83018035915067ffffffffffffffff821115611eb157600080fd5b602001915036819003821315611cd157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611f165760208186018101518583015201611efc565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f24565b8183823760009101908152919050565b600060208284031215611f8857600080fd5b5051919050565b818103818111156109da576109da611f24565b600082611fd8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f2456fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa2646970667358221220c618cb60ccea4d134580893ea1be714ea2f3ee81e84f2989f14e663d114ee00a64736f6c63430008140033", + "devdoc": { + "details": "This contract is the implementation. It is meant to be used through proxy clone.", + "kind": "dev", + "methods": { + "initialize(uint256,uint256)": { + "details": "This function is only callable once and needs to be called immediately after deployment by the factory in the same transaction.", + "params": { + "x_": "The x coordinate of the public key", + "y_": "The y coordinate of the public key" + } + }, + "isValidSignature(bytes,bytes)": { + "details": "This is the old version of the function of EIP-1271 using bytes memory instead of bytes32", + "params": { + "_hash": "The hash of the data signed", + "_signature": "The signature" + }, + "returns": { + "_0": "The EIP-1271 magic value" + } + }, + "isValidSignature(bytes32,bytes)": { + "params": { + "_hash": "The hash of the data signed", + "_signature": "The signature" + }, + "returns": { + "_0": "The EIP-1271 magic value" + } + } + }, + "title": "P256Signer", + "version": 1 + }, + "userdoc": { + "errors": { + "AlreadyInitialized()": [ + { + "notice": "Error message when the contract is already initialized" + } + ], + "InvalidHash()": [ + { + "notice": "Error message when the hash is invalid" + } + ], + "InvalidSignature()": [ + { + "notice": "Error message when the signature is invalid" + } + ] + }, + "kind": "user", + "methods": { + "initialized()": { + "notice": "Whether the contract has been initialized" + }, + "isValidSignature(bytes,bytes)": { + "notice": "Verifies that the signer is the owner of the secp256r1 public key." + }, + "isValidSignature(bytes32,bytes)": { + "notice": "Verifies that the signer is the owner of the secp256r1 public key." + }, + "x()": { + "notice": "The x coordinate of the secp256r1 public key" + }, + "y()": { + "notice": "The y coordinate of the secp256r1 public key" + } + }, + "notice": "A contract used to verify ECDSA signatures over secp256r1 through EIP-1271 of Webauthn payloads.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2870, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 2873, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "x", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 2876, + "contract": "contracts/P256Signer.sol:P256Signer", + "label": "y", + "offset": 0, + "slot": "2", + "type": "t_uint256" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/deployments/optimism_production/P256SignerFactory.json b/deployments/optimism_production/P256SignerFactory.json new file mode 100644 index 0000000..294160d --- /dev/null +++ b/deployments/optimism_production/P256SignerFactory.json @@ -0,0 +1,137 @@ +{ + "address": "0xa726C1619bB28cc0e1303eFEa80BbAF9FE42389f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "x", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "y", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "NewSignerCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "y", + "type": "uint256" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x57f991c60b372755f86690a773720139d9382784c407beb614ee0ced110232f9", + "receipt": { + "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", + "from": "0x61f2ad863873d2466B64cef9cdC65361F98A65D3", + "contractAddress": null, + "transactionIndex": 28, + "gasUsed": "195440", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1197492904bf9d8aab1e1c525ad0298019ccb7364c3a30750f581b714e4d1506", + "transactionHash": "0x57f991c60b372755f86690a773720139d9382784c407beb614ee0ced110232f9", + "logs": [], + "blockNumber": 117974149, + "cumulativeGasUsed": "3797229", + "status": 1, + "byzantium": true + }, + "args": [ + "0x93ae54DAE3A266d2F7197d118e1B3A89429ba55F" + ], + "numDeployments": 1, + "solcInputHash": "01c9a206ce5ca6951fd356b6a1b5a7d7", + "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"NewSignerCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"create(uint256,uint256)\":{\"params\":{\"x\":\"The x coordinate of the public key\",\"y\":\"The y coordinate of the public key\"}}},\"title\":\"P256SignerFactory\",\"version\":1},\"userdoc\":{\"events\":{\"NewSignerCreated(uint256,uint256,address)\":{\"notice\":\"Emitted when a new P256Signer proxy contract is created\"}},\"kind\":\"user\",\"methods\":{\"create(uint256,uint256)\":{\"notice\":\"Creates a new P256Signer proxy contract\"},\"implementation()\":{\"notice\":\"The implementation address of the P256Signer contract\"}},\"notice\":\"Factory contract for creating proxies for P256Signer\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/P256SignerFactory.sol\":\"P256SignerFactory\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"FreshCryptoLib/FCL_Webauthn.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_elliptic.sol\\n///*\\n///*\\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\nimport {FCL_ecdsa} from \\\"./FCL_ecdsa.sol\\\";\\n\\nimport {FCL_ecdsa_utils} from \\\"./FCL_ecdsa_utils.sol\\\";\\n\\nlibrary FCL_WebAuthn {\\n error InvalidAuthenticatorData();\\n error InvalidClientData();\\n error InvalidSignature();\\n\\n function WebAuthn_format(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata // rs\\n ) internal pure returns (bytes32 result) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n {\\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\\n revert InvalidAuthenticatorData();\\n }\\n // Verify that clientData commits to the expected client challenge\\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\\n bytes memory challengeExtracted = new bytes(\\n bytes(challengeEncoded).length\\n );\\n\\n assembly {\\n calldatacopy(\\n add(challengeExtracted, 32),\\n add(clientData.offset, clientChallengeDataOffset),\\n mload(challengeExtracted)\\n )\\n }\\n\\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\\n assembly {\\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\\n }\\n\\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\\n revert InvalidClientData();\\n }\\n } //avoid stack full\\n\\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\\n\\n assembly {\\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\\n }\\n\\n bytes32 more = sha256(clientData);\\n assembly {\\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\\n }\\n\\n return sha256(verifyData);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256[2] calldata Q\\n ) internal view returns (bool) {\\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\\n }\\n\\n function checkSignature (\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 Qx,\\n uint256 Qy\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\\n\\n return result;\\n }\\n\\n function checkSignature_prec(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n address dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\\n\\n return result;\\n }\\n\\n //beware that this implementation will not be compliant with EOF\\n function checkSignature_hackmem(\\n bytes calldata authenticatorData,\\n bytes1 authenticatorDataFlagMask,\\n bytes calldata clientData,\\n bytes32 clientChallenge,\\n uint256 clientChallengeDataOffset,\\n uint256[2] calldata rs,\\n uint256 dataPointer\\n ) internal view returns (bool) {\\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\\n\\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\\n );\\n\\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc2811ef6e17ea1d5509a3d3f7d5af5e56583347b36093d05530425d7c1316dd6\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa.sol\":{\"content\":\"//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n /**\\n * @dev ECDSA verification, given , signature, and public key, no calldata version\\n */\\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\\n\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n \\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n\\n x1= addmod(x1, n-r,n );\\n \\n return x1 == 0;\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n \\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n X= addmod(X, n-r,n );\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n}\\n\",\"keccak256\":\"0x679d2e9a655cd7e156a0cfc24de0aca88d4e0b34a8e0dfe6a599f23af092f5a2\",\"license\":\"MIT\"},\"FreshCryptoLib/FCL_ecdsa_utils.sol\":{\"content\":\"\\n//********************************************************************************************/\\n// ___ _ ___ _ _ _ _\\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\\n// | _| '_/ -_|_-< ' \\\\ | (__| '_| || | '_ \\\\ _/ _ \\\\ | |__| | '_ \\\\\\n// |_||_| \\\\___/__/_||_| \\\\___|_| \\\\_, | .__/\\\\__\\\\___/ |____|_|_.__/\\n// |__/|_|\\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\\n///* License: This software is licensed under MIT License\\n///* This Code may be reused including license and copyright notice.\\n///* See LICENSE file at the root folder of the project.\\n///* FILE: FCL_ecdsa.sol\\n///*\\n///*\\n///* DESCRIPTION: ecdsa verification implementation\\n///*\\n//**************************************************************************************/\\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\\n// if ever used for other curve than sec256R1\\n// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.19 <0.9.0;\\n\\n\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.sol\\\";\\n\\n\\n\\nlibrary FCL_ecdsa_utils {\\n // Set parameters for curve sec256r1.public\\n //curve order (number of points)\\n uint256 constant n = FCL_Elliptic_ZZ.n;\\n \\n /**\\n * @dev ECDSA verification, given , signature, and public key.\\n */\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return false;\\n }\\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\\n uint256 x1;\\n\\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\\n x1= addmod(x1, n-r,n );\\n \\n \\n return x1 == 0;\\n }\\n\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\n return ecdsa_verify(message, rs, Q[0], Q[1]);\\n }\\n\\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\\n {\\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\\n return address(0);\\n }\\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\n }\\n\\n\\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\\n //K is nonce, kpriv is private key\\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\\n {\\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \\n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n //ecdsa key derivation\\n //kpriv is private key return (x,y) coordinates of associated Pubkey\\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\\n {\\n \\n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\\n \\n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\\n {\\n y=FCL_Elliptic_ZZ.p-y;\\n } \\n\\n }\\n \\n //precomputations for 8 dimensional trick\\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\\n {\\n \\n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\\n \\n //the trivial private keys 1 and -1 are forbidden\\n if(Qx==FCL_Elliptic_ZZ.gx)\\n {\\n revert();\\n }\\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\\n \\n Pow64_PQ[4][0]=Qx;\\n Pow64_PQ[4][1]=Qy;\\n \\n /* raise to multiplication by 64 by 6 consecutive doubling*/\\n for(uint j=1;j<4;j++){\\n uint256 x;\\n uint256 y;\\n uint256 zz;\\n uint256 zzz;\\n \\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\\n \\t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\\n \\t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n\\n \\tfor(uint i=0;i<63;i++){\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\\n \\t}\\n }\\n \\n /* neutral point */\\n Prec[0][0]=0;\\n Prec[0][1]=0;\\n \\n \\t\\n for(uint i=1;i<256;i++)\\n { \\n Prec[i][0]=0;\\n Prec[i][1]=0;\\n \\n for(uint j=0;j<8;j++)\\n {\\n \\tif( (i&(1<=0.8.19 <0.9.0;\\n\\nlibrary FCL_Elliptic_ZZ {\\n // Set parameters for curve sec256r1.\\n\\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\\n //curve prime field modulus\\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n //short weierstrass first coefficient\\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\\n //short weierstrass second coefficient\\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\\n //generating point affine coordinates\\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\\n //curve order (number of points)\\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\\n /* -2 mod n constant, used to speed up inversion*/\\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\\n\\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\\n //P+1 div 4\\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\\n //arbitrary constant to express no quadratic residuosity\\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\\n\\n /**\\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\\n */\\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2modn)\\n mstore(add(pointer, 0xa0), n)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n /**\\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\\n */\\n\\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\\n assembly {\\n let pointer := mload(0x40)\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(pointer, 0x20)\\n mstore(add(pointer, 0x20), 0x20)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n mstore(add(pointer, 0x60), u)\\n mstore(add(pointer, 0x80), minus_2)\\n mstore(add(pointer, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\\n result := mload(pointer)\\n }\\n }\\n\\n //Coron projective shuffling, take as input alpha as blinding factor\\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n \\n uint256 alpha2=mulmod(alpha,alpha,p);\\n \\n x3=mulmod(alpha2, x,p); //alpha^-2.x\\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\\n\\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\\n \\n return (x3, y3, zz3, zzz3);\\n }\\n\\n\\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\\n {\\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\\n u2=addmod(u2, p-u1, p);// P = U2-U1\\n x1=mulmod(u2, u2, p);//PP\\n x2=mulmod(x1, u2, p);//PPP\\n \\n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \\n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\\n\\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \\n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\\n\\n return (x3, y3, zz3, zzz3);\\n }\\n\\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\\n/// @param self The integer of which to find the modular inverse\\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\\n\\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\\n assembly (\\\"memory-safe\\\") {\\n // load the free memory pointer value\\n let pointer := mload(0x40)\\n\\n // Define length of base (Bsize)\\n mstore(pointer, 0x20)\\n // Define the exponent size (Esize)\\n mstore(add(pointer, 0x20), 0x20)\\n // Define the modulus size (Msize)\\n mstore(add(pointer, 0x40), 0x20)\\n // Define variables base (B)\\n mstore(add(pointer, 0x60), self)\\n // Define the exponent (E)\\n mstore(add(pointer, 0x80), pp1div4)\\n // We save the point of the last argument, it will be override by the result\\n // of the precompile call in order to avoid paying for the memory expansion properly\\n let _result := add(pointer, 0xa0)\\n // Define the modulus (M)\\n mstore(_result, p)\\n\\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\\n if iszero(\\n staticcall(\\n not(0), // amount of gas to send\\n MODEXP_PRECOMPILE, // target\\n pointer, // argsOffset\\n 0xc0, // argsSize (6 * 32 bytes)\\n _result, // retOffset (we override M to avoid paying for the memory expansion)\\n 0x20 // retSize (32 bytes)\\n )\\n ) { revert(0, 0) }\\n\\n result := mload(_result)\\n// result :=addmod(result,0,p)\\n }\\n if(mulmod(result,result,p)!=self){\\n result=_NOTSQUARE;\\n }\\n \\n return result;\\n}\\n /**\\n * /* @dev Convert from affine rep to XYZZ rep\\n */\\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\\n unchecked {\\n P[2] = 1; //ZZ\\n P[3] = 1; //ZZZ\\n P[0] = x0;\\n P[1] = y0;\\n }\\n }\\n\\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \\n\\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\\n\\n y=SqrtMod(y2);\\n if(y==_NOTSQUARE){\\n return _NOTONCURVE;\\n }\\n if((y&1)!=(parity&1)){\\n y=p-y;\\n }\\n }\\n\\n /**\\n * /* @dev Convert from XYZZ rep to affine rep\\n */\\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\\n y1 = mulmod(y, zzzInv, p); //Y/zzz\\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\\n zzzInv = mulmod(_b, _b, p); //1/zz\\n x1 = mulmod(x, zzzInv, p); //X/zz\\n }\\n\\n /**\\n * /* @dev Sutherland2008 doubling\\n */\\n /* The \\\"dbl-2008-s-1\\\" doubling formulas */\\n\\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n assembly {\\n P0 := mulmod(2, y, p) //U = 2*Y1\\n P2 := mulmod(P0, P0, p) // V=U^2\\n P3 := mulmod(x, P2, p) // S = X1*V\\n P1 := mulmod(P0, P2, p) // W=UV\\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\\n }\\n }\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\\n */\\n\\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\\n internal\\n pure\\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\\n {\\n unchecked {\\n if (y1 == 0) {\\n return (x2, y2, 1, 1);\\n }\\n\\n assembly {\\n y1 := sub(p, y1)\\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\\n P0 := mulmod(x2, x2, p) //PP = P^2\\n P1 := mulmod(P0, x2, p) //PPP = P*PP\\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\\n }\\n //end assembly\\n } //end unchecked\\n return (P0, P1, P2, P3);\\n }\\n\\n /**\\n * @dev Return the zero curve in XYZZ coordinates.\\n */\\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\\n return (0, 0, 0, 0);\\n }\\n /**\\n * @dev Check if point is the neutral of the curve\\n */\\n\\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\\n return y0 == 0;\\n }\\n /**\\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\\n */\\n\\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\\n return (0, 0);\\n }\\n\\n /**\\n * @dev Check if the curve is the zero curve in affine rep.\\n */\\n // uint256 x, uint256 y)\\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\\n return (y == 0);\\n }\\n\\n /**\\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\\n */\\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\\n return false;\\n }\\n unchecked {\\n uint256 LHS = mulmod(y, y, p); // y^2\\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\\n\\n return LHS == RHS;\\n }\\n }\\n\\n /**\\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\\n */\\n\\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\\n uint256 zz0;\\n uint256 zzz0;\\n\\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\\n if((x0==x1)&&(y0==y1)) {\\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\\n }\\n else{\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\n }\\n\\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\\n }\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns only x for ECDSA use \\n * */\\n function ecZZ_mulmuladd_S_asm(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 Y;\\n uint256 index = 255;\\n uint256 H0;\\n uint256 H1;\\n\\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n\\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \\n if((H0==0)&&(H1==0))//handling Q=-G\\n {\\n scalar_u=addmod(scalar_u, n-scalar_v, n);\\n scalar_v=0;\\n if (scalar_u == 0 && scalar_v == 0) return 0;\\n }\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n X := H0\\n Y := H1\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := H0\\n T2 := H1\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n let T := mload(0x40)\\n mstore(add(T, 0x60), zz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n //Y:=mulmod(Y,zzz,p)//Y/zzz\\n //zz :=mulmod(zz, mload(T),p) //1/z\\n //zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, mload(T), p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return X;\\n }\\n\\n\\n /**\\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\\n * Returns affine representation of point (normalized) \\n * */\\n function ecZZ_mulmuladd(\\n uint256 Q0,\\n uint256 Q1, //affine rep for input point Q\\n uint256 scalar_u,\\n uint256 scalar_v\\n ) internal view returns (uint256 X, uint256 Y) {\\n uint256 zz;\\n uint256 zzz;\\n uint256 index = 255;\\n uint256[6] memory T;\\n uint256[2] memory H;\\n \\n unchecked {\\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\\n\\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\\n\\n assembly {\\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\\n index := sub(index, 1)\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n } {}\\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if eq(zz, 1) {\\n X := gx\\n Y := gy\\n }\\n if eq(zz, 2) {\\n X := Q0\\n Y := Q1\\n }\\n if eq(zz, 3) {\\n Y := mload(add(H,32))\\n X := mload(H)\\n }\\n\\n index := sub(index, 1)\\n zz := 1\\n zzz := 1\\n\\n for {} gt(minus_1, index) { index := sub(index, 1) } {\\n // inlined EcZZ_Dbl\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n {\\n //value of dibit\\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\\n\\n if iszero(T4) {\\n Y := sub(p, Y) //restore the -Y inversion\\n continue\\n } // if T4!=0\\n\\n if eq(T4, 1) {\\n T1 := gx\\n T2 := gy\\n }\\n if eq(T4, 2) {\\n T1 := Q0\\n T2 := Q1\\n }\\n if eq(T4, 3) {\\n T1 := mload(H)\\n T2 := mload(add(H,32))\\n }\\n if iszero(zz) {\\n X := T1\\n Y := T2\\n zz := 1\\n zzz := 1\\n continue\\n }\\n // inlined EcZZ_AddN\\n\\n //T3:=sub(p, Y)\\n //T3:=Y\\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\\n\\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\\n //todo : construct edge vector case\\n if iszero(y2) {\\n if iszero(T2) {\\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n T4 := mulmod(T2, T2, p) //PP\\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\\n zz := mulmod(zz, T4, p)\\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\\n let TT2 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\\n\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zzz)\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n Y:=mulmod(Y,mload(T),p)//Y/zzz\\n zz :=mulmod(zz, mload(T),p) //1/z\\n zz:= mulmod(zz,zz,p) //1/zz\\n X := mulmod(X, zz, p) //X/zz\\n } //end assembly\\n } //end unchecked\\n\\n return (X,Y);\\n }\\n\\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\\n //contract at given address dataPointer\\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\\n // the external tool to generate tables from public key is in the /sage directory\\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n unchecked {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n extcodecopy(dataPointer, T, mload(T), 64)\\n let index := sub(zz, 1)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for {} gt(index, 191) { index := add(index, 191) } {\\n //inline Double\\n {\\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(TT1, TT1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n let T1 := mulmod(TT1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n }\\n {\\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n let index2 := sub(index, 64)\\n let T3 :=\\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\\n let index3 := sub(index2, 64)\\n let T2 :=\\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\\n index := sub(index3, 64)\\n let T1 :=\\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T1) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n extcodecopy(dataPointer, T, T1, 64)\\n }\\n\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n\\n // inlined EcZZ_AddN\\n if iszero(zz) {\\n X := mload(T)\\n Y := mload(add(T, 32))\\n zz := 1\\n zzz := 1\\n\\n continue\\n }\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n\\n //special case ecAdd(P,P)=EcDbl\\n if iszero(y2) {\\n if iszero(T2) {\\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\\n T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n\\n T1 := mulmod(T1, T2, p) // W=UV\\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\\n\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\\n\\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\\n\\n continue\\n }\\n }\\n\\n let T4 := mulmod(T2, T2, p)\\n let T1 := mulmod(T4, T2, p) //\\n zz := mulmod(zz, T4, p)\\n //zzz3=V*ZZ1\\n zzz := mulmod(zzz, T1, p) // W=UV/\\n let zz1 := mulmod(X, T4, p)\\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n \\n\\n // improving the extcodecopy trick : append array at end of contract\\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\\n internal view\\n returns (uint256 X /*, uint Y*/ )\\n {\\n uint256 zz; // third and coordinates of the point\\n\\n uint256[6] memory T;\\n zz = 256; //start index\\n\\n unchecked {\\n while (T[0] == 0) {\\n zz = zz - 1;\\n //tbd case of msb octobit is null\\n T[0] = 64\\n * (\\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\\n );\\n }\\n assembly {\\n codecopy(T, add(mload(T), dataPointer), 64)\\n X := mload(T)\\n let Y := mload(add(T, 32))\\n let zzz := 1\\n zz := 1\\n\\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\\n let T2 := mulmod(T1, T1, p) // V=U^2\\n let T3 := mulmod(X, T2, p) // S = X1*V\\n T1 := mulmod(T1, T2, p) // W=UV\\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\\n\\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\\n\\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\\n\\n /* compute element to access in precomputed table */\\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\\n index := sub(index, 64)\\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\\n //index:=add(index,192), restore index, interleaved with loop\\n\\n //tbd: check validity of formulae with (0,1) to remove conditional jump\\n if iszero(T4) {\\n Y := sub(p, Y)\\n\\n continue\\n }\\n {\\n /* Access to precomputed table using extcodecopy hack */\\n codecopy(T, add(T4, dataPointer), 64)\\n\\n // inlined EcZZ_AddN\\n\\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\\n T4 := mulmod(T2, T2, p)\\n T1 := mulmod(T4, T2, p)\\n T2 := mulmod(zz, T4, p) // W=UV\\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\\n let zz1 := mulmod(X, T4, p)\\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\\n zz := T2\\n X := T4\\n }\\n } //end loop\\n mstore(add(T, 0x60), zz)\\n\\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\\n mstore(T, 0x20)\\n mstore(add(T, 0x20), 0x20)\\n mstore(add(T, 0x40), 0x20)\\n // Define variables base, exponent and modulus\\n //mstore(add(pointer, 0x60), u)\\n mstore(add(T, 0x80), minus_2)\\n mstore(add(T, 0xa0), p)\\n\\n // Call the precompiled contract 0x05 = ModExp\\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\\n\\n zz := mload(T)\\n X := mulmod(X, zz, p) //X/zz\\n }\\n } //end unchecked\\n }\\n\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n /**\\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\\n * generation of contract bytecode for precomputations is done using sagemath code\\n * (see sage directory, WebAuthn_precompute.sage)\\n */\\n\\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\\n internal view\\n returns (bool)\\n {\\n uint256 r = rs[0];\\n uint256 s = rs[1];\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return false;\\n }\\n /* Q is pushed via bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\n\\n\\n\\n} //EOF\\n\",\"keccak256\":\"0x7f244805668cc589ae33f18c35c68738db25994c9befbb5d07f28a91fb03ba44\",\"license\":\"MIT\"},\"FreshCryptoLib/utils/Base64Url.sol\":{\"content\":\"// SPDX-License-Identifier: Apache-2.0\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Encode (without '=' padding) \\n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\\n */\\nlibrary Base64Url {\\n /**\\n * @dev Base64Url Encoding Table\\n */\\n string internal constant ENCODING_TABLE =\\n \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\\\";\\n\\n function encode(bytes memory data) internal pure returns (string memory) {\\n if (data.length == 0) return \\\"\\\";\\n\\n // Load the table into memory\\n string memory table = ENCODING_TABLE;\\n\\n string memory result = new string(4 * ((data.length + 2) / 3));\\n\\n // @solidity memory-safe-assembly\\n assembly {\\n let tablePtr := add(table, 1)\\n let resultPtr := add(result, 32)\\n\\n for {\\n let dataPtr := data\\n let endPtr := add(data, mload(data))\\n } lt(dataPtr, endPtr) {\\n\\n } {\\n dataPtr := add(dataPtr, 3)\\n let input := mload(dataPtr)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(\\n resultPtr,\\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\\n )\\n resultPtr := add(resultPtr, 1)\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n resultPtr := add(resultPtr, 1)\\n }\\n\\n // Remove the padding adjustment logic\\n switch mod(mload(data), 3)\\n case 1 {\\n // Adjust for the last byte of data\\n resultPtr := sub(resultPtr, 2)\\n }\\n case 2 {\\n // Adjust for the last two bytes of data\\n resultPtr := sub(resultPtr, 1)\\n }\\n \\n // Set the correct length of the result string\\n mstore(result, sub(resultPtr, add(result, 32)))\\n }\\n\\n return result; \\n }\\n}\\n\",\"keccak256\":\"0xc9d5fbb0ef9ff0756eb5aabe7a32b2bf0f8f3c533d4451dd5778fe77aee7f0c1\",\"license\":\"Apache-2.0\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title P256Signer\\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This contract is the implementation. It is meant to be used through\\n/// proxy clone.\\ncontract P256Signer {\\n /// @notice The EIP-1271 magic value\\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\\n\\n /// @notice The old EIP-1271 magic value\\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\\n\\n /// @notice Whether the contract has been initialized\\n bool public initialized;\\n\\n /// @notice The x coordinate of the secp256r1 public key\\n uint256 public x;\\n\\n /// @notice The y coordinate of the secp256r1 public key\\n uint256 public y;\\n\\n /// @notice Error message when the signature is invalid\\n error InvalidSignature();\\n\\n /// @notice Error message when the hash is invalid\\n error InvalidHash();\\n\\n /// @notice Error message when the contract is already initialized\\n error AlreadyInitialized();\\n\\n constructor() {\\n initialized = true;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(abi.encode(_hash), _signature);\\n return EIP1271_MAGICVALUE;\\n }\\n\\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\\n /// @dev This is the old version of the function of EIP-1271 using bytes\\n /// memory instead of bytes32\\n /// @param _hash The hash of the data signed\\n /// @param _signature The signature\\n /// @return The EIP-1271 magic value\\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\n }\\n\\n struct SignatureLayout {\\n bytes authenticatorData;\\n bytes clientData;\\n uint256 challengeOffset;\\n uint256[2] rs;\\n }\\n\\n /// @notice Validates the signature\\n /// @param data The data signed\\n /// @param _signature The signature\\n function _validate(bytes memory data, bytes calldata _signature) private view {\\n bytes32 _hash = keccak256(data);\\n SignatureLayout calldata signaturePointer;\\n // This code should precalculate the offsets of variables as defined in the layout\\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\\n assembly {\\n signaturePointer := _signature.offset\\n }\\n\\n bool valid = FCL_WebAuthn.checkSignature(\\n signaturePointer.authenticatorData,\\n 0x01,\\n signaturePointer.clientData,\\n _hash,\\n signaturePointer.challengeOffset,\\n signaturePointer.rs,\\n x,\\n y\\n );\\n\\n if (!valid) revert InvalidSignature();\\n }\\n\\n /// @dev This function is only callable once and needs to be called immediately\\n /// after deployment by the factory in the same transaction.\\n /// @param x_ The x coordinate of the public key\\n /// @param y_ The y coordinate of the public key\\n function initialize(uint256 x_, uint256 y_) external {\\n if (initialized) revert AlreadyInitialized();\\n initialized = true;\\n x = x_;\\n y = y_;\\n }\\n}\\n\",\"keccak256\":\"0xfc1b006adb6ace0364918015a1aa64439374f813383bcc71290f6b37b66641e5\"},\"contracts/P256SignerFactory.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {P256Signer} from \\\"./P256Signer.sol\\\";\\nimport \\\"solady/src/utils/LibClone.sol\\\";\\n\\n/// @title P256SignerFactory\\n/// @notice Factory contract for creating proxies for P256Signer\\ncontract P256SignerFactory {\\n /// @notice The implementation address of the P256Signer contract\\n address public immutable implementation;\\n\\n constructor(address implementation_) {\\n implementation = implementation_;\\n }\\n\\n /// @notice Emitted when a new P256Signer proxy contract is created\\n event NewSignerCreated(uint256 indexed x, uint256 indexed y, address signer);\\n\\n /// @notice Creates a new P256Signer proxy contract\\n /// @param x The x coordinate of the public key\\n /// @param y The y coordinate of the public key\\n function create(uint256 x, uint256 y) external returns (address) {\\n bytes32 salt = keccak256(abi.encodePacked(x, y));\\n address signer = LibClone.cloneDeterministic(implementation, salt);\\n P256Signer(signer).initialize(x, y);\\n emit NewSignerCreated(x, y, signer);\\n return signer;\\n }\\n}\\n\",\"keccak256\":\"0x3bdac08bf7a1c4c1621474b10733f74a9487359212705bbca42ec678aa549a53\"},\"solady/src/utils/LibClone.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Minimal proxy library.\\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)\\n/// @author Minimal proxy by 0age (https://github.com/0age)\\n/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie\\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\\n///\\n/// @dev Minimal proxy:\\n/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,\\n/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,\\n/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.\\n///\\n/// @dev Minimal proxy (PUSH0 variant):\\n/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.\\n/// It is optimized first for minimal runtime gas, then for minimal bytecode.\\n/// The PUSH0 clone functions are intentionally postfixed with a jarring \\\"_PUSH0\\\" as\\n/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.\\n/// Please use with caution.\\n///\\n/// @dev Clones with immutable args (CWIA):\\n/// The implementation of CWIA here implements a `receive()` method that emits the\\n/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,\\n/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards\\n/// composability. The minimal proxy implementation does not offer this feature.\\nlibrary LibClone {\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* CUSTOM ERRORS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Unable to deploy the clone.\\n error DeploymentFailed();\\n\\n /// @dev The salt must start with either the zero address or the caller.\\n error SaltDoesNotStartWithCaller();\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* MINIMAL PROXY OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a clone of `implementation`.\\n function clone(address implementation) internal returns (address instance) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n /**\\n * --------------------------------------------------------------------------+\\n * CREATION (9 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * 60 runSize | PUSH1 runSize | r | |\\n * 3d | RETURNDATASIZE | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * --------------------------------------------------------------------------|\\n * RUNTIME (44 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * |\\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | 0 | |\\n * 3d | RETURNDATASIZE | 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 0 0 | |\\n * |\\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |\\n * 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |\\n * 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |\\n * |\\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |\\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |\\n * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |\\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |\\n * |\\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |\\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |\\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |\\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\\n * |\\n * 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |\\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\\n * |\\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * --------------------------------------------------------------------------+\\n */\\n\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n instance := create(0, 0x0c, 0x35)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Deploys a deterministic clone of `implementation` with `salt`.\\n function cloneDeterministic(address implementation, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n instance := create2(0, 0x0c, 0x35, salt)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the clone of `implementation`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash(address implementation) internal pure returns (bytes32 hash) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\\n mstore(0x14, implementation)\\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\\n hash := keccak256(0x0c, 0x35)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x21, 0)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic clone of `implementation`,\\n /// with `salt` by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)\\n internal\\n pure\\n returns (address predicted)\\n {\\n bytes32 hash = initCodeHash(implementation);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a PUSH0 clone of `implementation`.\\n function clone_PUSH0(address implementation) internal returns (address instance) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n /**\\n * --------------------------------------------------------------------------+\\n * CREATION (9 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * 60 runSize | PUSH1 runSize | r | |\\n * 5f | PUSH0 | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 5f | PUSH0 | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * --------------------------------------------------------------------------|\\n * RUNTIME (45 bytes) |\\n * --------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * --------------------------------------------------------------------------|\\n * |\\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\\n * 5f | PUSH0 | 0 | |\\n * 5f | PUSH0 | 0 0 | |\\n * |\\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 | |\\n * 5f | PUSH0 | 0 cds 0 0 | |\\n * 5f | PUSH0 | 0 0 cds 0 0 | |\\n * 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |\\n * |\\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |\\n * 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |\\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |\\n * 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |\\n * f4 | DELEGATECALL | success | [0..cds): calldata |\\n * |\\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success | [0..cds): calldata |\\n * 5f | PUSH0 | 0 rds success | [0..cds): calldata |\\n * 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |\\n * 3e | RETURNDATACOPY | success | [0..rds): returndata |\\n * |\\n * 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |\\n * 57 | JUMPI | | [0..rds): returndata |\\n * |\\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | | [0..rds): returndata |\\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * --------------------------------------------------------------------------+\\n */\\n\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n instance := create(0, 0x0e, 0x36)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\\n function cloneDeterministic_PUSH0(address implementation, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n instance := create2(0, 0x0e, 0x36, salt)\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\\n mstore(0x14, implementation) // 20\\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\\n hash := keccak256(0x0e, 0x36)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x24, 0)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,\\n /// with `salt` by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress_PUSH0(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n bytes32 hash = initCodeHash_PUSH0(implementation);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* CLONES WITH IMMUTABLE ARGS OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys a minimal proxy with `implementation`,\\n /// using immutable arguments encoded in `data`.\\n ///\\n /// Note: This implementation of CWIA differs from the original implementation.\\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\\n function clone(address implementation, bytes memory data) internal returns (address instance) {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n // The `creationSize` is `extraLength + 108`\\n // The `runSize` is `creationSize - 10`.\\n\\n /**\\n * ---------------------------------------------------------------------------------------------------+\\n * CREATION (10 bytes) |\\n * ---------------------------------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * ---------------------------------------------------------------------------------------------------|\\n * 61 runSize | PUSH2 runSize | r | |\\n * 3d | RETURNDATASIZE | 0 r | |\\n * 81 | DUP2 | r 0 r | |\\n * 60 offset | PUSH1 offset | o r 0 r | |\\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\\n * f3 | RETURN | | [0..runSize): runtime code |\\n * ---------------------------------------------------------------------------------------------------|\\n * RUNTIME (98 bytes + extraLength) |\\n * ---------------------------------------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * ---------------------------------------------------------------------------------------------------|\\n * |\\n * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds | |\\n * 60 0x2c | PUSH1 0x2c | 0x2c cds | |\\n * 57 | JUMPI | | |\\n * 34 | CALLVALUE | cv | |\\n * 3d | RETURNDATASIZE | 0 cv | |\\n * 52 | MSTORE | | [0..0x20): callvalue |\\n * 7f sig | PUSH32 0x9e.. | sig | [0..0x20): callvalue |\\n * 59 | MSIZE | 0x20 sig | [0..0x20): callvalue |\\n * 3d | RETURNDATASIZE | 0 0x20 sig | [0..0x20): callvalue |\\n * a1 | LOG1 | | [0..0x20): callvalue |\\n * 00 | STOP | | [0..0x20): callvalue |\\n * 5b | JUMPDEST | | |\\n * |\\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds | |\\n * 3d | RETURNDATASIZE | 0 cds | |\\n * 3d | RETURNDATASIZE | 0 0 cds | |\\n * 37 | CALLDATACOPY | | [0..cds): calldata |\\n * |\\n * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata |\\n * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata |\\n * |\\n * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata |\\n * 60 0x62 | PUSH1 0x62 | 0x62 e e 0 0 0 0 | [0..cds): calldata |\\n * 36 | CALLDATASIZE | cds 0x62 e e 0 0 0 0 | [0..cds): calldata |\\n * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * |\\n * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * |\\n * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\\n * |\\n * 60 0x60 | PUSH1 0x60 | 0x60 success 0 rds | [0..rds): returndata |\\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\\n * |\\n * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * fd | REVERT | | [0..rds): returndata |\\n * |\\n * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\\n * f3 | RETURN | | [0..rds): returndata |\\n * ---------------------------------------------------------------------------------------------------+\\n */\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\\n // The actual EVM limit may be smaller and may change over time.\\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Create the instance.\\n instance := create(0, sub(data, 0x4c), add(extraLength, 0x6c))\\n\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Deploys a deterministic clone of `implementation`,\\n /// using immutable arguments encoded in `data`, with `salt`.\\n ///\\n /// Note: This implementation of CWIA differs from the original implementation.\\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\\n function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)\\n internal\\n returns (address instance)\\n {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\\n // The actual EVM limit may be smaller and may change over time.\\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Create the instance.\\n instance := create2(0, sub(data, 0x4c), add(extraLength, 0x6c), salt)\\n\\n // If `instance` is zero, revert.\\n if iszero(instance) {\\n // Store the function selector of `DeploymentFailed()`.\\n mstore(0x00, 0x30116425)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Returns the initialization code hash of the clone of `implementation`\\n /// using immutable arguments encoded in `data`.\\n /// Used for mining vanity addresses with create2crunch.\\n function initCodeHash(address implementation, bytes memory data)\\n internal\\n pure\\n returns (bytes32 hash)\\n {\\n assembly {\\n // Compute the boundaries of the data and cache the memory slots around it.\\n let mBefore3 := mload(sub(data, 0x60))\\n let mBefore2 := mload(sub(data, 0x40))\\n let mBefore1 := mload(sub(data, 0x20))\\n let dataLength := mload(data)\\n let dataEnd := add(add(data, 0x20), dataLength)\\n let mAfter1 := mload(dataEnd)\\n\\n // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.\\n // The actual EVM limit may be smaller and may change over time.\\n returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))\\n\\n // +2 bytes for telling how much data there is appended to the call.\\n let extraLength := add(dataLength, 2)\\n\\n // Write the bytecode before the data.\\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\\n // Write the address of the implementation.\\n mstore(sub(data, 0x0d), implementation)\\n // Write the rest of the bytecode.\\n mstore(\\n sub(data, 0x21),\\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\\n )\\n // `keccak256(\\\"ReceiveETH(uint256)\\\")`\\n mstore(\\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\\n )\\n mstore(\\n sub(data, 0x5a),\\n or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)\\n )\\n mstore(dataEnd, shl(0xf0, extraLength))\\n\\n // Compute and store the bytecode hash.\\n hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))\\n\\n // Restore the overwritten memory surrounding `data`.\\n mstore(dataEnd, mAfter1)\\n mstore(data, dataLength)\\n mstore(sub(data, 0x20), mBefore1)\\n mstore(sub(data, 0x40), mBefore2)\\n mstore(sub(data, 0x60), mBefore3)\\n }\\n }\\n\\n /// @dev Returns the address of the deterministic clone of\\n /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(\\n address implementation,\\n bytes memory data,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n bytes32 hash = initCodeHash(implementation, data);\\n predicted = predictDeterministicAddress(hash, salt, deployer);\\n }\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* OTHER OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Returns the address when a contract with initialization code hash,\\n /// `hash`, is deployed with `salt`, by `deployer`.\\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\\n function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)\\n internal\\n pure\\n returns (address predicted)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Compute and store the bytecode hash.\\n mstore8(0x00, 0xff) // Write the prefix.\\n mstore(0x35, hash)\\n mstore(0x01, shl(96, deployer))\\n mstore(0x15, salt)\\n predicted := keccak256(0x00, 0x55)\\n // Restore the part of the free memory pointer that has been overwritten.\\n mstore(0x35, 0)\\n }\\n }\\n\\n /// @dev Reverts if `salt` does not start with either the zero address or the caller.\\n function checkStartsWithCaller(bytes32 salt) internal view {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // If the salt does not start with the zero address or the caller.\\n if iszero(or(iszero(shr(96, salt)), eq(caller(), shr(96, salt)))) {\\n // Store the function selector of `SaltDoesNotStartWithCaller()`.\\n mstore(0x00, 0x2f634836)\\n // Revert with (offset, size).\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x159b64c65da9e6efe93b8df8c6bb1c7672a7511dcaba414aaa3e447f6d7065e6\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d8b0407d1a28cd9f0ad691ad81667640a0419d8054ee5121c474b80b2ce9bf0064736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d8b0407d1a28cd9f0ad691ad81667640a0419d8054ee5121c474b80b2ce9bf0064736f6c63430008140033", + "devdoc": { + "kind": "dev", + "methods": { + "create(uint256,uint256)": { + "params": { + "x": "The x coordinate of the public key", + "y": "The y coordinate of the public key" + } + } + }, + "title": "P256SignerFactory", + "version": 1 + }, + "userdoc": { + "events": { + "NewSignerCreated(uint256,uint256,address)": { + "notice": "Emitted when a new P256Signer proxy contract is created" + } + }, + "kind": "user", + "methods": { + "create(uint256,uint256)": { + "notice": "Creates a new P256Signer proxy contract" + }, + "implementation()": { + "notice": "The implementation address of the P256Signer contract" + } + }, + "notice": "Factory contract for creating proxies for P256Signer", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/optimism_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json b/deployments/optimism_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json new file mode 100644 index 0000000..2c01ac3 --- /dev/null +++ b/deployments/optimism_production/solcInputs/01c9a206ce5ca6951fd356b6a1b5a7d7.json @@ -0,0 +1,57 @@ +{ + "language": "Solidity", + "sources": { + "contracts/P256Signer.sol": { + "content": "pragma solidity ^0.8.0;\n\nimport {FCL_WebAuthn} from \"FreshCryptoLib/FCL_Webauthn.sol\";\n\n/// @title P256Signer\n/// @notice A contract used to verify ECDSA signatures over secp256r1 through\n/// EIP-1271 of Webauthn payloads.\n/// @dev This contract is the implementation. It is meant to be used through\n/// proxy clone.\ncontract P256Signer {\n /// @notice The EIP-1271 magic value\n bytes4 internal constant EIP1271_MAGICVALUE = 0x1626ba7e;\n\n /// @notice The old EIP-1271 magic value\n bytes4 internal constant OLD_EIP1271_MAGICVALUE = 0x20c13b0b;\n\n /// @notice Whether the contract has been initialized\n bool public initialized;\n\n /// @notice The x coordinate of the secp256r1 public key\n uint256 public x;\n\n /// @notice The y coordinate of the secp256r1 public key\n uint256 public y;\n\n /// @notice Error message when the signature is invalid\n error InvalidSignature();\n\n /// @notice Error message when the hash is invalid\n error InvalidHash();\n\n /// @notice Error message when the contract is already initialized\n error AlreadyInitialized();\n\n constructor() {\n initialized = true;\n }\n\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\n /// @param _hash The hash of the data signed\n /// @param _signature The signature\n /// @return The EIP-1271 magic value\n function isValidSignature(bytes32 _hash, bytes calldata _signature) public view returns (bytes4) {\n _validate(abi.encode(_hash), _signature);\n return EIP1271_MAGICVALUE;\n }\n\n /// @notice Verifies that the signer is the owner of the secp256r1 public key.\n /// @dev This is the old version of the function of EIP-1271 using bytes\n /// memory instead of bytes32\n /// @param _hash The hash of the data signed\n /// @param _signature The signature\n /// @return The EIP-1271 magic value\n function isValidSignature(bytes memory _hash, bytes calldata _signature) public view returns (bytes4) {\n _validate(_hash, _signature);\n return OLD_EIP1271_MAGICVALUE;\n }\n\n struct SignatureLayout {\n bytes authenticatorData;\n bytes clientData;\n uint256 challengeOffset;\n uint256[2] rs;\n }\n\n /// @notice Validates the signature\n /// @param data The data signed\n /// @param _signature The signature\n function _validate(bytes memory data, bytes calldata _signature) private view {\n bytes32 _hash = keccak256(data);\n SignatureLayout calldata signaturePointer;\n // This code should precalculate the offsets of variables as defined in the layout\n // Calldata variables are represented as offsets, and, I think, length for dynamic types\n // If the calldata is malformed (e.g., shorter than expected), this will revert with an out of bounds error\n assembly {\n signaturePointer := _signature.offset\n }\n\n bool valid = FCL_WebAuthn.checkSignature(\n signaturePointer.authenticatorData,\n 0x01,\n signaturePointer.clientData,\n _hash,\n signaturePointer.challengeOffset,\n signaturePointer.rs,\n x,\n y\n );\n\n if (!valid) revert InvalidSignature();\n }\n\n /// @dev This function is only callable once and needs to be called immediately\n /// after deployment by the factory in the same transaction.\n /// @param x_ The x coordinate of the public key\n /// @param y_ The y coordinate of the public key\n function initialize(uint256 x_, uint256 y_) external {\n if (initialized) revert AlreadyInitialized();\n initialized = true;\n x = x_;\n y = y_;\n }\n}\n" + }, + "contracts/P256SignerFactory.sol": { + "content": "pragma solidity ^0.8.0;\n\nimport {P256Signer} from \"./P256Signer.sol\";\nimport \"solady/src/utils/LibClone.sol\";\n\n/// @title P256SignerFactory\n/// @notice Factory contract for creating proxies for P256Signer\ncontract P256SignerFactory {\n /// @notice The implementation address of the P256Signer contract\n address public immutable implementation;\n\n constructor(address implementation_) {\n implementation = implementation_;\n }\n\n /// @notice Emitted when a new P256Signer proxy contract is created\n event NewSignerCreated(uint256 indexed x, uint256 indexed y, address signer);\n\n /// @notice Creates a new P256Signer proxy contract\n /// @param x The x coordinate of the public key\n /// @param y The y coordinate of the public key\n function create(uint256 x, uint256 y) external returns (address) {\n bytes32 salt = keccak256(abi.encodePacked(x, y));\n address signer = LibClone.cloneDeterministic(implementation, salt);\n P256Signer(signer).initialize(x, y);\n emit NewSignerCreated(x, y, signer);\n return signer;\n }\n}\n" + }, + "FreshCryptoLib/FCL_ecdsa_utils.sol": { + "content": "\n//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n// |__/|_|\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_ecdsa.sol\n///*\n///*\n///* DESCRIPTION: ecdsa verification implementation\n///*\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\n\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\n\n\n\nlibrary FCL_ecdsa_utils {\n // Set parameters for curve sec256r1.public\n //curve order (number of points)\n uint256 constant n = FCL_Elliptic_ZZ.n;\n \n /**\n * @dev ECDSA verification, given , signature, and public key.\n */\n\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256 Qx, uint256 Qy) internal view returns (bool) {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return false;\n }\n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\n return false;\n }\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\n uint256 x1;\n\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\n x1= addmod(x1, n-r,n );\n \n \n return x1 == 0;\n }\n\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\n return ecdsa_verify(message, rs, Q[0], Q[1]);\n }\n\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\n {\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return address(0);\n }\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\n\n uint256 Qx;\n uint256 Qy;\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\n\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\n }\n\n\n //ecdsa signature for test purpose only (who would like to have a private key onchain anyway ?)\n //K is nonce, kpriv is private key\n function ecdsa_sign(bytes32 message, uint256 k , uint256 kpriv) internal view returns(uint256 r, uint256 s)\n {\n r=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, k, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\n r=addmod(0,r, FCL_Elliptic_ZZ.n); \n s=mulmod(FCL_Elliptic_ZZ.FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n),FCL_Elliptic_ZZ.n);//s=k^-1.(h+r.kpriv)\n\n \n if(r==0||s==0){\n revert();\n }\n\n\n }\n\n //ecdsa key derivation\n //kpriv is private key return (x,y) coordinates of associated Pubkey\n function ecdsa_derivKpub(uint256 kpriv) internal view returns(uint256 x, uint256 y)\n {\n \n x=FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(0,0, kpriv, 0) ;//Calculate the curve point k.G (abuse ecmulmul add with v=0)\n y=FCL_Elliptic_ZZ.ec_Decompress(x, 1);\n \n if (FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(x, y, kpriv, FCL_Elliptic_ZZ.n - 1) != 0) //extract correct y value\n {\n y=FCL_Elliptic_ZZ.p-y;\n } \n\n }\n \n //precomputations for 8 dimensional trick\n function Precalc_8dim( uint256 Qx, uint256 Qy) internal view returns( uint[2][256] memory Prec)\n {\n \n uint[2][8] memory Pow64_PQ; //store P, 64P, 128P, 192P, Q, 64Q, 128Q, 192Q\n \n //the trivial private keys 1 and -1 are forbidden\n if(Qx==FCL_Elliptic_ZZ.gx)\n {\n revert();\n }\n Pow64_PQ[0][0]=FCL_Elliptic_ZZ.gx;\n Pow64_PQ[0][1]=FCL_Elliptic_ZZ.gy;\n \n Pow64_PQ[4][0]=Qx;\n Pow64_PQ[4][1]=Qy;\n \n /* raise to multiplication by 64 by 6 consecutive doubling*/\n for(uint j=1;j<4;j++){\n uint256 x;\n uint256 y;\n uint256 zz;\n uint256 zzz;\n \n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j-1][0], Pow64_PQ[j-1][1], 1, 1);\n \t(Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n (x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+3][0], Pow64_PQ[j+3][1], 1, 1);\n \t(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n\n \tfor(uint i=0;i<63;i++){\n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j][0], Pow64_PQ[j][1],1,1);\n (Pow64_PQ[j][0], Pow64_PQ[j][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n \t(x,y,zz,zzz)=FCL_Elliptic_ZZ.ecZZ_Dbl(Pow64_PQ[j+4][0], Pow64_PQ[j+4][1],1,1);\n (Pow64_PQ[j+4][0], Pow64_PQ[j+4][1])=FCL_Elliptic_ZZ.ecZZ_SetAff(x,y,zz,zzz);\n \t}\n }\n \n /* neutral point */\n Prec[0][0]=0;\n Prec[0][1]=0;\n \n \t\n for(uint i=1;i<256;i++)\n { \n Prec[i][0]=0;\n Prec[i][1]=0;\n \n for(uint j=0;j<8;j++)\n {\n \tif( (i&(1<=0.8.19 <0.9.0;\n\n\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\n\n\n\nlibrary FCL_ecdsa {\n // Set parameters for curve sec256r1.public\n //curve order (number of points)\n uint256 constant n = FCL_Elliptic_ZZ.n;\n \n /**\n * @dev ECDSA verification, given , signature, and public key.\n */\n\n /**\n * @dev ECDSA verification, given , signature, and public key, no calldata version\n */\n function ecdsa_verify(bytes32 message, uint256 r, uint256 s, uint256 Qx, uint256 Qy) internal view returns (bool){\n\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return false;\n }\n \n if (!FCL_Elliptic_ZZ.ecAff_isOnCurve(Qx, Qy)) {\n return false;\n }\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 scalar_u = mulmod(uint256(message), sInv, FCL_Elliptic_ZZ.n);\n uint256 scalar_v = mulmod(r, sInv, FCL_Elliptic_ZZ.n);\n uint256 x1;\n\n x1 = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S_asm(Qx, Qy, scalar_u, scalar_v);\n\n x1= addmod(x1, n-r,n );\n \n return x1 == 0;\n }\n\n function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) internal view returns (address)\n {\n if (r == 0 || r >= FCL_Elliptic_ZZ.n || s == 0 || s >= FCL_Elliptic_ZZ.n) {\n return address(0);\n }\n uint256 y=FCL_Elliptic_ZZ.ec_Decompress(r, v-27);\n uint256 rinv=FCL_Elliptic_ZZ.FCL_nModInv(r);\n uint256 u1=mulmod(FCL_Elliptic_ZZ.n-addmod(0,h,FCL_Elliptic_ZZ.n), rinv,FCL_Elliptic_ZZ.n);//-hr^-1\n uint256 u2=mulmod(s, rinv,FCL_Elliptic_ZZ.n);//sr^-1\n\n uint256 Qx;\n uint256 Qy;\n (Qx,Qy)=FCL_Elliptic_ZZ.ecZZ_mulmuladd(r,y, u1, u2);\n\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\n }\n\n function ecdsa_precomputed_verify(bytes32 message, uint256 r, uint256 s, address Shamir8)\n internal view\n returns (bool)\n {\n \n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 X;\n\n //Shamir 8 dimensions\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\n\n X= addmod(X, n-r,n );\n\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n function ecdsa_precomputed_verify(bytes32 message, uint256[2] calldata rs, address Shamir8)\n internal view\n returns (bool)\n {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via the contract at address Shamir8 assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_Elliptic_ZZ.FCL_nModInv(s);\n\n uint256 X;\n\n //Shamir 8 dimensions\n X = FCL_Elliptic_ZZ.ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\n\n X= addmod(X, n-r,n );\n\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n}\n" + }, + "FreshCryptoLib/FCL_elliptic.sol": { + "content": "//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n// |__/|_|\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_elliptic.sol\n///*\n///*\n///* DESCRIPTION: modified XYZZ system coordinates for EVM elliptic point multiplication\n///* optimization\n///*\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\nlibrary FCL_Elliptic_ZZ {\n // Set parameters for curve sec256r1.\n\n // address of the ModExp precompiled contract (Arbitrary-precision exponentiation under modulo)\n address constant MODEXP_PRECOMPILE = 0x0000000000000000000000000000000000000005;\n //curve prime field modulus\n uint256 constant p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n //short weierstrass first coefficient\n uint256 constant a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;\n //short weierstrass second coefficient\n uint256 constant b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;\n //generating point affine coordinates\n uint256 constant gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;\n uint256 constant gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;\n //curve order (number of points)\n uint256 constant n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;\n /* -2 mod p constant, used to speed up inversion and doubling (avoid negation)*/\n uint256 constant minus_2 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;\n /* -2 mod n constant, used to speed up inversion*/\n uint256 constant minus_2modn = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;\n\n uint256 constant minus_1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n //P+1 div 4\n uint256 constant pp1div4=0x3fffffffc0000000400000000000000000000000400000000000000000000000;\n //arbitrary constant to express no quadratic residuosity\n uint256 constant _NOTSQUARE=0xFFFFFFFF00000002000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n uint256 constant _NOTONCURVE=0xFFFFFFFF00000003000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;\n\n /**\n * /* inversion mod n via a^(n-2), use of precompiled using little Fermat theorem\n */\n function FCL_nModInv(uint256 u) internal view returns (uint256 result) {\n assembly {\n let pointer := mload(0x40)\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(pointer, 0x20)\n mstore(add(pointer, 0x20), 0x20)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base, exponent and modulus\n mstore(add(pointer, 0x60), u)\n mstore(add(pointer, 0x80), minus_2modn)\n mstore(add(pointer, 0xa0), n)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\n result := mload(pointer)\n }\n }\n /**\n * /* @dev inversion mod nusing little Fermat theorem via a^(n-2), use of precompiled\n */\n\n function FCL_pModInv(uint256 u) internal view returns (uint256 result) {\n assembly {\n let pointer := mload(0x40)\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(pointer, 0x20)\n mstore(add(pointer, 0x20), 0x20)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base, exponent and modulus\n mstore(add(pointer, 0x60), u)\n mstore(add(pointer, 0x80), minus_2)\n mstore(add(pointer, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, pointer, 0xc0, pointer, 0x20)) { revert(0, 0) }\n result := mload(pointer)\n }\n }\n\n //Coron projective shuffling, take as input alpha as blinding factor\n function ecZZ_Coronize(uint256 alpha, uint256 x, uint256 y, uint256 zz, uint256 zzz) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\n {\n \n uint256 alpha2=mulmod(alpha,alpha,p);\n \n x3=mulmod(alpha2, x,p); //alpha^-2.x\n y3=mulmod(mulmod(alpha, alpha2,p), y,p);\n\n zz3=mulmod(zz,alpha2,p);//alpha^2 zz\n zzz3=mulmod(zzz,mulmod(alpha, alpha2,p),p);//alpha^3 zzz\n \n return (x3, y3, zz3, zzz3);\n }\n\n\n function ecZZ_Add(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2, uint256 zz2, uint256 zzz2) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3)\n {\n uint256 u1=mulmod(x1,zz2,p); // U1 = X1*ZZ2\n uint256 u2=mulmod(x2, zz1,p); // U2 = X2*ZZ1\n u2=addmod(u2, p-u1, p);// P = U2-U1\n x1=mulmod(u2, u2, p);//PP\n x2=mulmod(x1, u2, p);//PPP\n \n zz3=mulmod(x1, mulmod(zz1, zz2, p),p);//ZZ3 = ZZ1*ZZ2*PP \n zzz3=mulmod(zzz1, mulmod(zzz2, x2, p),p);//ZZZ3 = ZZZ1*ZZZ2*PPP\n\n zz1=mulmod(y1, zzz2,p); // S1 = Y1*ZZZ2\n zz2=mulmod(y2, zzz1, p); // S2 = Y2*ZZZ1 \n zz2=addmod(zz2, p-zz1, p);//R = S2-S1\n zzz1=mulmod(u1, x1,p); //Q = U1*PP\n x3= addmod(addmod(mulmod(zz2, zz2, p), p-x2,p), mulmod(minus_2, zzz1,p),p); //X3 = R2-PPP-2*Q\n y3=addmod( mulmod(zz2, addmod(zzz1, p-x3, p),p), p-mulmod(zz1, x2, p),p);//R*(Q-X3)-S1*PPP\n\n return (x3, y3, zz3, zzz3);\n }\n\n/// @notice Calculate one modular square root of a given integer. Assume that p=3 mod 4.\n/// @dev Uses the ModExp precompiled contract at address 0x05 for fast computation using little Fermat theorem\n/// @param self The integer of which to find the modular inverse\n/// @return result The modular inverse of the input integer. If the modular inverse doesn't exist, it revert the tx\n\nfunction SqrtMod(uint256 self) internal view returns (uint256 result){\n assembly (\"memory-safe\") {\n // load the free memory pointer value\n let pointer := mload(0x40)\n\n // Define length of base (Bsize)\n mstore(pointer, 0x20)\n // Define the exponent size (Esize)\n mstore(add(pointer, 0x20), 0x20)\n // Define the modulus size (Msize)\n mstore(add(pointer, 0x40), 0x20)\n // Define variables base (B)\n mstore(add(pointer, 0x60), self)\n // Define the exponent (E)\n mstore(add(pointer, 0x80), pp1div4)\n // We save the point of the last argument, it will be override by the result\n // of the precompile call in order to avoid paying for the memory expansion properly\n let _result := add(pointer, 0xa0)\n // Define the modulus (M)\n mstore(_result, p)\n\n // Call the precompiled ModExp (0x05) https://www.evm.codes/precompiled#0x05\n if iszero(\n staticcall(\n not(0), // amount of gas to send\n MODEXP_PRECOMPILE, // target\n pointer, // argsOffset\n 0xc0, // argsSize (6 * 32 bytes)\n _result, // retOffset (we override M to avoid paying for the memory expansion)\n 0x20 // retSize (32 bytes)\n )\n ) { revert(0, 0) }\n\n result := mload(_result)\n// result :=addmod(result,0,p)\n }\n if(mulmod(result,result,p)!=self){\n result=_NOTSQUARE;\n }\n \n return result;\n}\n /**\n * /* @dev Convert from affine rep to XYZZ rep\n */\n function ecAff_SetZZ(uint256 x0, uint256 y0) internal pure returns (uint256[4] memory P) {\n unchecked {\n P[2] = 1; //ZZ\n P[3] = 1; //ZZZ\n P[0] = x0;\n P[1] = y0;\n }\n }\n\n function ec_Decompress(uint256 x, uint256 parity) internal view returns(uint256 y){ \n\n uint256 y2=mulmod(x,mulmod(x,x,p),p);//x3\n y2=addmod(b,addmod(y2,mulmod(x,a,p),p),p);//x3+ax+b\n\n y=SqrtMod(y2);\n if(y==_NOTSQUARE){\n return _NOTONCURVE;\n }\n if((y&1)!=(parity&1)){\n y=p-y;\n }\n }\n\n /**\n * /* @dev Convert from XYZZ rep to affine rep\n */\n /* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-add-2008-s*/\n function ecZZ_SetAff(uint256 x, uint256 y, uint256 zz, uint256 zzz) internal view returns (uint256 x1, uint256 y1) {\n uint256 zzzInv = FCL_pModInv(zzz); //1/zzz\n y1 = mulmod(y, zzzInv, p); //Y/zzz\n uint256 _b = mulmod(zz, zzzInv, p); //1/z\n zzzInv = mulmod(_b, _b, p); //1/zz\n x1 = mulmod(x, zzzInv, p); //X/zz\n }\n\n /**\n * /* @dev Sutherland2008 doubling\n */\n /* The \"dbl-2008-s-1\" doubling formulas */\n\n function ecZZ_Dbl(uint256 x, uint256 y, uint256 zz, uint256 zzz)\n internal\n pure\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\n {\n unchecked {\n assembly {\n P0 := mulmod(2, y, p) //U = 2*Y1\n P2 := mulmod(P0, P0, p) // V=U^2\n P3 := mulmod(x, P2, p) // S = X1*V\n P1 := mulmod(P0, P2, p) // W=UV\n P2 := mulmod(P2, zz, p) //zz3=V*ZZ1\n zz := mulmod(3, mulmod(addmod(x, sub(p, zz), p), addmod(x, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n P0 := addmod(mulmod(zz, zz, p), mulmod(minus_2, P3, p), p) //X3=M^2-2S\n x := mulmod(zz, addmod(P3, sub(p, P0), p), p) //M(S-X3)\n P3 := mulmod(P1, zzz, p) //zzz3=W*zzz1\n P1 := addmod(x, sub(p, mulmod(P1, y, p)), p) //Y3= M(S-X3)-W*Y1\n }\n }\n return (P0, P1, P2, P3);\n }\n\n /**\n * @dev Sutherland2008 add a ZZ point with a normalized point and greedy formulae\n * warning: assume that P1(x1,y1)!=P2(x2,y2), true in multiplication loop with prime order (cofactor 1)\n */\n\n function ecZZ_AddN(uint256 x1, uint256 y1, uint256 zz1, uint256 zzz1, uint256 x2, uint256 y2)\n internal\n pure\n returns (uint256 P0, uint256 P1, uint256 P2, uint256 P3)\n {\n unchecked {\n if (y1 == 0) {\n return (x2, y2, 1, 1);\n }\n\n assembly {\n y1 := sub(p, y1)\n y2 := addmod(mulmod(y2, zzz1, p), y1, p)\n x2 := addmod(mulmod(x2, zz1, p), sub(p, x1), p)\n P0 := mulmod(x2, x2, p) //PP = P^2\n P1 := mulmod(P0, x2, p) //PPP = P*PP\n P2 := mulmod(zz1, P0, p) ////ZZ3 = ZZ1*PP\n P3 := mulmod(zzz1, P1, p) ////ZZZ3 = ZZZ1*PPP\n zz1 := mulmod(x1, P0, p) //Q = X1*PP\n P0 := addmod(addmod(mulmod(y2, y2, p), sub(p, P1), p), mulmod(minus_2, zz1, p), p) //R^2-PPP-2*Q\n P1 := addmod(mulmod(addmod(zz1, sub(p, P0), p), y2, p), mulmod(y1, P1, p), p) //R*(Q-X3)\n }\n //end assembly\n } //end unchecked\n return (P0, P1, P2, P3);\n }\n\n /**\n * @dev Return the zero curve in XYZZ coordinates.\n */\n function ecZZ_SetZero() internal pure returns (uint256 x, uint256 y, uint256 zz, uint256 zzz) {\n return (0, 0, 0, 0);\n }\n /**\n * @dev Check if point is the neutral of the curve\n */\n\n // uint256 x0, uint256 y0, uint256 zz0, uint256 zzz0\n function ecZZ_IsZero(uint256, uint256 y0, uint256, uint256) internal pure returns (bool) {\n return y0 == 0;\n }\n /**\n * @dev Return the zero curve in affine coordinates. Compatible with the double formulae (no special case)\n */\n\n function ecAff_SetZero() internal pure returns (uint256 x, uint256 y) {\n return (0, 0);\n }\n\n /**\n * @dev Check if the curve is the zero curve in affine rep.\n */\n // uint256 x, uint256 y)\n function ecAff_IsZero(uint256, uint256 y) internal pure returns (bool flag) {\n return (y == 0);\n }\n\n /**\n * @dev Check if a point in affine coordinates is on the curve (reject Neutral that is indeed on the curve).\n */\n function ecAff_isOnCurve(uint256 x, uint256 y) internal pure returns (bool) {\n if ( ((0 == x)&&( 0 == y)) || (x == p && y == p)) {\n return false;\n }\n unchecked {\n uint256 LHS = mulmod(y, y, p); // y^2\n uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(x, a, p), p); // x^3+ax\n RHS = addmod(RHS, b, p); // x^3 + a*x + b\n\n return LHS == RHS;\n }\n }\n\n /**\n * @dev Add two elliptic curve points in affine coordinates. Deal with P=Q\n */\n\n function ecAff_add(uint256 x0, uint256 y0, uint256 x1, uint256 y1) internal view returns (uint256, uint256) {\n uint256 zz0;\n uint256 zzz0;\n\n if (ecAff_IsZero(x0, y0)) return (x1, y1);\n if (ecAff_IsZero(x1, y1)) return (x0, y0);\n if((x0==x1)&&(y0==y1)) {\n (x0, y0, zz0, zzz0) = ecZZ_Dbl(x0, y0,1,1);\n }\n else{\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\n }\n\n return ecZZ_SetAff(x0, y0, zz0, zzz0);\n }\n\n /**\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\n * Returns only x for ECDSA use \n * */\n function ecZZ_mulmuladd_S_asm(\n uint256 Q0,\n uint256 Q1, //affine rep for input point Q\n uint256 scalar_u,\n uint256 scalar_v\n ) internal view returns (uint256 X) {\n uint256 zz;\n uint256 zzz;\n uint256 Y;\n uint256 index = 255;\n uint256 H0;\n uint256 H1;\n\n unchecked {\n if (scalar_u == 0 && scalar_v == 0) return 0;\n\n (H0, H1) = ecAff_add(gx, gy, Q0, Q1); \n if((H0==0)&&(H1==0))//handling Q=-G\n {\n scalar_u=addmod(scalar_u, n-scalar_v, n);\n scalar_v=0;\n if (scalar_u == 0 && scalar_v == 0) return 0;\n }\n assembly {\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\n index := sub(index, 1)\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n } {}\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if eq(zz, 1) {\n X := gx\n Y := gy\n }\n if eq(zz, 2) {\n X := Q0\n Y := Q1\n }\n if eq(zz, 3) {\n X := H0\n Y := H1\n }\n\n index := sub(index, 1)\n zz := 1\n zzz := 1\n\n for {} gt(minus_1, index) { index := sub(index, 1) } {\n // inlined EcZZ_Dbl\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n {\n //value of dibit\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if iszero(T4) {\n Y := sub(p, Y) //restore the -Y inversion\n continue\n } // if T4!=0\n\n if eq(T4, 1) {\n T1 := gx\n T2 := gy\n }\n if eq(T4, 2) {\n T1 := Q0\n T2 := Q1\n }\n if eq(T4, 3) {\n T1 := H0\n T2 := H1\n }\n if iszero(zz) {\n X := T1\n Y := T2\n zz := 1\n zzz := 1\n continue\n }\n // inlined EcZZ_AddN\n\n //T3:=sub(p, Y)\n //T3:=Y\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\n\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\n //todo : construct edge vector case\n if iszero(y2) {\n if iszero(T2) {\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n T4 := mulmod(T2, T2, p) //PP\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\n zz := mulmod(zz, T4, p)\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\n let TT2 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\n\n X := T4\n }\n } //end loop\n let T := mload(0x40)\n mstore(add(T, 0x60), zz)\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n //Y:=mulmod(Y,zzz,p)//Y/zzz\n //zz :=mulmod(zz, mload(T),p) //1/z\n //zz:= mulmod(zz,zz,p) //1/zz\n X := mulmod(X, mload(T), p) //X/zz\n } //end assembly\n } //end unchecked\n\n return X;\n }\n\n\n /**\n * @dev Computation of uG+vQ using Strauss-Shamir's trick, G basepoint, Q public key\n * Returns affine representation of point (normalized) \n * */\n function ecZZ_mulmuladd(\n uint256 Q0,\n uint256 Q1, //affine rep for input point Q\n uint256 scalar_u,\n uint256 scalar_v\n ) internal view returns (uint256 X, uint256 Y) {\n uint256 zz;\n uint256 zzz;\n uint256 index = 255;\n uint256[6] memory T;\n uint256[2] memory H;\n \n unchecked {\n if (scalar_u == 0 && scalar_v == 0) return (0,0);\n\n (H[0], H[1]) = ecAff_add(gx, gy, Q0, Q1); //will not work if Q=P, obvious forbidden private key\n\n assembly {\n for { let T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1)) } eq(T4, 0) {\n index := sub(index, 1)\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n } {}\n zz := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if eq(zz, 1) {\n X := gx\n Y := gy\n }\n if eq(zz, 2) {\n X := Q0\n Y := Q1\n }\n if eq(zz, 3) {\n Y := mload(add(H,32))\n X := mload(H)\n }\n\n index := sub(index, 1)\n zz := 1\n zzz := 1\n\n for {} gt(minus_1, index) { index := sub(index, 1) } {\n // inlined EcZZ_Dbl\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n {\n //value of dibit\n T4 := add(shl(1, and(shr(index, scalar_v), 1)), and(shr(index, scalar_u), 1))\n\n if iszero(T4) {\n Y := sub(p, Y) //restore the -Y inversion\n continue\n } // if T4!=0\n\n if eq(T4, 1) {\n T1 := gx\n T2 := gy\n }\n if eq(T4, 2) {\n T1 := Q0\n T2 := Q1\n }\n if eq(T4, 3) {\n T1 := mload(H)\n T2 := mload(add(H,32))\n }\n if iszero(zz) {\n X := T1\n Y := T2\n zz := 1\n zzz := 1\n continue\n }\n // inlined EcZZ_AddN\n\n //T3:=sub(p, Y)\n //T3:=Y\n let y2 := addmod(mulmod(T2, zzz, p), Y, p) //R\n T2 := addmod(mulmod(T1, zz, p), sub(p, X), p) //P\n\n //special extremely rare case accumulator where EcAdd is replaced by EcDbl, no need to optimize this\n //todo : construct edge vector case\n if iszero(y2) {\n if iszero(T2) {\n T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n T4 := mulmod(T2, T2, p) //PP\n let TT1 := mulmod(T4, T2, p) //PPP, this one could be spared, but adding this register spare gas\n zz := mulmod(zz, T4, p)\n zzz := mulmod(zzz, TT1, p) //zz3=V*ZZ1\n let TT2 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, TT1), p), mulmod(minus_2, TT2, p), p)\n Y := addmod(mulmod(addmod(TT2, sub(p, T4), p), y2, p), mulmod(Y, TT1, p), p)\n\n X := T4\n }\n } //end loop\n mstore(add(T, 0x60), zzz)\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n Y:=mulmod(Y,mload(T),p)//Y/zzz\n zz :=mulmod(zz, mload(T),p) //1/z\n zz:= mulmod(zz,zz,p) //1/zz\n X := mulmod(X, zz, p) //X/zz\n } //end assembly\n } //end unchecked\n\n return (X,Y);\n }\n\n //8 dimensions Shamir's trick, using precomputations stored in Shamir8, stored as Bytecode of an external\n //contract at given address dataPointer\n //(thx to Lakhdar https://github.com/Kelvyne for EVM storage explanations and tricks)\n // the external tool to generate tables from public key is in the /sage directory\n function ecZZ_mulmuladd_S8_extcode(uint256 scalar_u, uint256 scalar_v, address dataPointer)\n internal view\n returns (uint256 X /*, uint Y*/ )\n {\n unchecked {\n uint256 zz; // third and coordinates of the point\n\n uint256[6] memory T;\n zz = 256; //start index\n\n while (T[0] == 0) {\n zz = zz - 1;\n //tbd case of msb octobit is null\n T[0] = 64\n * (\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\n );\n }\n assembly {\n extcodecopy(dataPointer, T, mload(T), 64)\n let index := sub(zz, 1)\n X := mload(T)\n let Y := mload(add(T, 32))\n let zzz := 1\n zz := 1\n\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\n for {} gt(index, 191) { index := add(index, 191) } {\n //inline Double\n {\n let TT1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(TT1, TT1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n let T1 := mulmod(TT1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\n let T5 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\n Y := addmod(mulmod(T1, Y, p), T5, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n /* compute element to access in precomputed table */\n }\n {\n let T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\n let index2 := sub(index, 64)\n let T3 :=\n add(T4, add(shl(12, and(shr(index2, scalar_v), 1)), shl(8, and(shr(index2, scalar_u), 1))))\n let index3 := sub(index2, 64)\n let T2 :=\n add(T3, add(shl(11, and(shr(index3, scalar_v), 1)), shl(7, and(shr(index3, scalar_u), 1))))\n index := sub(index3, 64)\n let T1 :=\n add(T2, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\n\n //tbd: check validity of formulae with (0,1) to remove conditional jump\n if iszero(T1) {\n Y := sub(p, Y)\n\n continue\n }\n extcodecopy(dataPointer, T, T1, 64)\n }\n\n {\n /* Access to precomputed table using extcodecopy hack */\n\n // inlined EcZZ_AddN\n if iszero(zz) {\n X := mload(T)\n Y := mload(add(T, 32))\n zz := 1\n zzz := 1\n\n continue\n }\n\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\n let T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\n\n //special case ecAdd(P,P)=EcDbl\n if iszero(y2) {\n if iszero(T2) {\n let T1 := mulmod(minus_2, Y, p) //U = 2*Y1, y free\n T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n\n T1 := mulmod(T1, T2, p) // W=UV\n y2 := mulmod(addmod(X, zz, p), addmod(X, sub(p, zz), p), p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M=3*(X-ZZ)(X+ZZ)\n\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n T2 := mulmod(T4, addmod(T3, sub(p, X), p), p) //M(S-X3)\n\n Y := addmod(T2, mulmod(T1, Y, p), p) //Y3= M(S-X3)-W*Y1\n\n continue\n }\n }\n\n let T4 := mulmod(T2, T2, p)\n let T1 := mulmod(T4, T2, p) //\n zz := mulmod(zz, T4, p)\n //zzz3=V*ZZ1\n zzz := mulmod(zzz, T1, p) // W=UV/\n let zz1 := mulmod(X, T4, p)\n X := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\n Y := addmod(mulmod(addmod(zz1, sub(p, X), p), y2, p), mulmod(Y, T1, p), p)\n }\n } //end loop\n mstore(add(T, 0x60), zz)\n\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n zz := mload(T)\n X := mulmod(X, zz, p) //X/zz\n }\n } //end unchecked\n }\n\n \n\n // improving the extcodecopy trick : append array at end of contract\n function ecZZ_mulmuladd_S8_hackmem(uint256 scalar_u, uint256 scalar_v, uint256 dataPointer)\n internal view\n returns (uint256 X /*, uint Y*/ )\n {\n uint256 zz; // third and coordinates of the point\n\n uint256[6] memory T;\n zz = 256; //start index\n\n unchecked {\n while (T[0] == 0) {\n zz = zz - 1;\n //tbd case of msb octobit is null\n T[0] = 64\n * (\n 128 * ((scalar_v >> zz) & 1) + 64 * ((scalar_v >> (zz - 64)) & 1)\n + 32 * ((scalar_v >> (zz - 128)) & 1) + 16 * ((scalar_v >> (zz - 192)) & 1)\n + 8 * ((scalar_u >> zz) & 1) + 4 * ((scalar_u >> (zz - 64)) & 1)\n + 2 * ((scalar_u >> (zz - 128)) & 1) + ((scalar_u >> (zz - 192)) & 1)\n );\n }\n assembly {\n codecopy(T, add(mload(T), dataPointer), 64)\n X := mload(T)\n let Y := mload(add(T, 32))\n let zzz := 1\n zz := 1\n\n //loop over 1/4 of scalars thx to Shamir's trick over 8 points\n for { let index := 254 } gt(index, 191) { index := add(index, 191) } {\n let T1 := mulmod(2, Y, p) //U = 2*Y1, y free\n let T2 := mulmod(T1, T1, p) // V=U^2\n let T3 := mulmod(X, T2, p) // S = X1*V\n T1 := mulmod(T1, T2, p) // W=UV\n let T4 := mulmod(3, mulmod(addmod(X, sub(p, zz), p), addmod(X, zz, p), p), p) //M=3*(X1-ZZ1)*(X1+ZZ1)\n zzz := mulmod(T1, zzz, p) //zzz3=W*zzz1\n zz := mulmod(T2, zz, p) //zz3=V*ZZ1, V free\n\n X := addmod(mulmod(T4, T4, p), mulmod(minus_2, T3, p), p) //X3=M^2-2S\n //T2:=mulmod(T4,addmod(T3, sub(p, X),p),p)//M(S-X3)\n T2 := mulmod(T4, addmod(X, sub(p, T3), p), p) //-M(S-X3)=M(X3-S)\n\n //Y:= addmod(T2, sub(p, mulmod(T1, Y ,p)),p )//Y3= M(S-X3)-W*Y1\n Y := addmod(mulmod(T1, Y, p), T2, p) //-Y3= W*Y1-M(S-X3), we replace Y by -Y to avoid a sub in ecAdd\n\n /* compute element to access in precomputed table */\n T4 := add(shl(13, and(shr(index, scalar_v), 1)), shl(9, and(shr(index, scalar_u), 1)))\n index := sub(index, 64)\n T4 := add(T4, add(shl(12, and(shr(index, scalar_v), 1)), shl(8, and(shr(index, scalar_u), 1))))\n index := sub(index, 64)\n T4 := add(T4, add(shl(11, and(shr(index, scalar_v), 1)), shl(7, and(shr(index, scalar_u), 1))))\n index := sub(index, 64)\n T4 := add(T4, add(shl(10, and(shr(index, scalar_v), 1)), shl(6, and(shr(index, scalar_u), 1))))\n //index:=add(index,192), restore index, interleaved with loop\n\n //tbd: check validity of formulae with (0,1) to remove conditional jump\n if iszero(T4) {\n Y := sub(p, Y)\n\n continue\n }\n {\n /* Access to precomputed table using extcodecopy hack */\n codecopy(T, add(T4, dataPointer), 64)\n\n // inlined EcZZ_AddN\n\n let y2 := addmod(mulmod(mload(add(T, 32)), zzz, p), Y, p)\n T2 := addmod(mulmod(mload(T), zz, p), sub(p, X), p)\n T4 := mulmod(T2, T2, p)\n T1 := mulmod(T4, T2, p)\n T2 := mulmod(zz, T4, p) // W=UV\n zzz := mulmod(zzz, T1, p) //zz3=V*ZZ1\n let zz1 := mulmod(X, T4, p)\n T4 := addmod(addmod(mulmod(y2, y2, p), sub(p, T1), p), mulmod(minus_2, zz1, p), p)\n Y := addmod(mulmod(addmod(zz1, sub(p, T4), p), y2, p), mulmod(Y, T1, p), p)\n zz := T2\n X := T4\n }\n } //end loop\n mstore(add(T, 0x60), zz)\n\n //(X,Y)=ecZZ_SetAff(X,Y,zz, zzz);\n //T[0] = inverseModp_Hard(T[0], p); //1/zzz, inline modular inversion using precompile:\n // Define length of base, exponent and modulus. 0x20 == 32 bytes\n mstore(T, 0x20)\n mstore(add(T, 0x20), 0x20)\n mstore(add(T, 0x40), 0x20)\n // Define variables base, exponent and modulus\n //mstore(add(pointer, 0x60), u)\n mstore(add(T, 0x80), minus_2)\n mstore(add(T, 0xa0), p)\n\n // Call the precompiled contract 0x05 = ModExp\n if iszero(staticcall(not(0), 0x05, T, 0xc0, T, 0x20)) { revert(0, 0) }\n\n zz := mload(T)\n X := mulmod(X, zz, p) //X/zz\n }\n } //end unchecked\n }\n\n\n /**\n * @dev ECDSA verification using a precomputed table of multiples of P and Q stored in contract at address Shamir8\n * generation of contract bytecode for precomputations is done using sagemath code\n * (see sage directory, WebAuthn_precompute.sage)\n */\n\n /**\n * @dev ECDSA verification using a precomputed table of multiples of P and Q appended at end of contract at address endcontract\n * generation of contract bytecode for precomputations is done using sagemath code\n * (see sage directory, WebAuthn_precompute.sage)\n */\n\n function ecdsa_precomputed_hackmem(bytes32 message, uint256[2] calldata rs, uint256 endcontract)\n internal view\n returns (bool)\n {\n uint256 r = rs[0];\n uint256 s = rs[1];\n if (r == 0 || r >= n || s == 0 || s >= n) {\n return false;\n }\n /* Q is pushed via bytecode assumed to be correct\n if (!isOnCurve(Q[0], Q[1])) {\n return false;\n }*/\n\n uint256 sInv = FCL_nModInv(s);\n uint256 X;\n\n //Shamir 8 dimensions\n X = ecZZ_mulmuladd_S8_hackmem(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), endcontract);\n\n assembly {\n X := addmod(X, sub(n, r), n)\n }\n return X == 0;\n } //end ecdsa_precomputed_verify()\n\n\n\n} //EOF\n" + }, + "FreshCryptoLib/FCL_Webauthn.sol": { + "content": "//********************************************************************************************/\n// ___ _ ___ _ _ _ _\n// | __| _ ___ __| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__\n// | _| '_/ -_|_-< ' \\ | (__| '_| || | '_ \\ _/ _ \\ | |__| | '_ \\\n// |_||_| \\___/__/_||_| \\___|_| \\_, | .__/\\__\\___/ |____|_|_.__/\n///* Copyright (C) 2022 - Renaud Dubois - This file is part of FCL (Fresh CryptoLib) project\n///* License: This software is licensed under MIT License\n///* This Code may be reused including license and copyright notice.\n///* See LICENSE file at the root folder of the project.\n///* FILE: FCL_elliptic.sol\n///*\n///*\n///* DESCRIPTION: Implementation of the WebAuthn Authentication mechanism\n///* https://www.w3.org/TR/webauthn-2/#sctn-intro\n///* Original code extracted from https://github.com/btchip/Webauthn.sol\n//**************************************************************************************/\n//* WARNING: this code SHALL not be used for non prime order curves for security reasons.\n// Code is optimized for a=-3 only curves with prime order, constant like -1, -2 shall be replaced\n// if ever used for other curve than sec256R1\n// SPDX-License-Identifier: MIT\npragma solidity >=0.8.19 <0.9.0;\n\nimport {Base64Url} from \"./utils/Base64Url.sol\";\nimport {FCL_Elliptic_ZZ} from \"./FCL_elliptic.sol\";\nimport {FCL_ecdsa} from \"./FCL_ecdsa.sol\";\n\nimport {FCL_ecdsa_utils} from \"./FCL_ecdsa_utils.sol\";\n\nlibrary FCL_WebAuthn {\n error InvalidAuthenticatorData();\n error InvalidClientData();\n error InvalidSignature();\n\n function WebAuthn_format(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata // rs\n ) internal pure returns (bytes32 result) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n {\n if ((authenticatorData[32] & authenticatorDataFlagMask) != authenticatorDataFlagMask) {\n revert InvalidAuthenticatorData();\n }\n // Verify that clientData commits to the expected client challenge\n // Use the Base64Url encoding which omits padding characters to match WebAuthn Specification\n string memory challengeEncoded = Base64Url.encode(abi.encodePacked(clientChallenge));\n bytes memory challengeExtracted = new bytes(\n bytes(challengeEncoded).length\n );\n\n assembly {\n calldatacopy(\n add(challengeExtracted, 32),\n add(clientData.offset, clientChallengeDataOffset),\n mload(challengeExtracted)\n )\n }\n\n bytes32 moreData; //=keccak256(abi.encodePacked(challengeExtracted));\n assembly {\n moreData := keccak256(add(challengeExtracted, 32), mload(challengeExtracted))\n }\n\n if (keccak256(abi.encodePacked(bytes(challengeEncoded))) != moreData) {\n revert InvalidClientData();\n }\n } //avoid stack full\n\n // Verify the signature over sha256(authenticatorData || sha256(clientData))\n bytes memory verifyData = new bytes(authenticatorData.length + 32);\n\n assembly {\n calldatacopy(add(verifyData, 32), authenticatorData.offset, authenticatorData.length)\n }\n\n bytes32 more = sha256(clientData);\n assembly {\n mstore(add(verifyData, add(authenticatorData.length, 32)), more)\n }\n\n return sha256(verifyData);\n }\n\n function checkSignature (\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256[2] calldata Q\n ) internal view returns (bool) {\n return checkSignature(authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs, Q[0], Q[1]);\n }\n\n function checkSignature (\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256 Qx,\n uint256 Qy\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_ecdsa_utils.ecdsa_verify(message, rs, Qx, Qy);\n\n return result;\n }\n\n function checkSignature_prec(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n address dataPointer\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_ecdsa.ecdsa_precomputed_verify(message, rs, dataPointer);\n\n return result;\n }\n\n //beware that this implementation will not be compliant with EOF\n function checkSignature_hackmem(\n bytes calldata authenticatorData,\n bytes1 authenticatorDataFlagMask,\n bytes calldata clientData,\n bytes32 clientChallenge,\n uint256 clientChallengeDataOffset,\n uint256[2] calldata rs,\n uint256 dataPointer\n ) internal view returns (bool) {\n // Let the caller check if User Presence (0x01) or User Verification (0x04) are set\n\n bytes32 message = FCL_WebAuthn.WebAuthn_format(\n authenticatorData, authenticatorDataFlagMask, clientData, clientChallenge, clientChallengeDataOffset, rs\n );\n\n bool result = FCL_Elliptic_ZZ.ecdsa_precomputed_hackmem(message, rs, dataPointer);\n\n return result;\n }\n}\n" + }, + "FreshCryptoLib/utils/Base64Url.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\n/**\n * @dev Encode (without '=' padding) \n * @author evmbrahmin, adapted from hiromin's Base64URL libraries\n */\nlibrary Base64Url {\n /**\n * @dev Base64Url Encoding Table\n */\n string internal constant ENCODING_TABLE =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\n function encode(bytes memory data) internal pure returns (string memory) {\n if (data.length == 0) return \"\";\n\n // Load the table into memory\n string memory table = ENCODING_TABLE;\n\n string memory result = new string(4 * ((data.length + 2) / 3));\n\n // @solidity memory-safe-assembly\n assembly {\n let tablePtr := add(table, 1)\n let resultPtr := add(result, 32)\n\n for {\n let dataPtr := data\n let endPtr := add(data, mload(data))\n } lt(dataPtr, endPtr) {\n\n } {\n dataPtr := add(dataPtr, 3)\n let input := mload(dataPtr)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(18, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(12, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(\n resultPtr,\n mload(add(tablePtr, and(shr(6, input), 0x3F)))\n )\n resultPtr := add(resultPtr, 1)\n\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n resultPtr := add(resultPtr, 1)\n }\n\n // Remove the padding adjustment logic\n switch mod(mload(data), 3)\n case 1 {\n // Adjust for the last byte of data\n resultPtr := sub(resultPtr, 2)\n }\n case 2 {\n // Adjust for the last two bytes of data\n resultPtr := sub(resultPtr, 1)\n }\n \n // Set the correct length of the result string\n mstore(result, sub(resultPtr, add(result, 32)))\n }\n\n return result; \n }\n}\n" + }, + "solady/src/utils/LibClone.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Minimal proxy library.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)\n/// @author Minimal proxy by 0age (https://github.com/0age)\n/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie\n/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)\n///\n/// @dev Minimal proxy:\n/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,\n/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,\n/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.\n///\n/// @dev Minimal proxy (PUSH0 variant):\n/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.\n/// It is optimized first for minimal runtime gas, then for minimal bytecode.\n/// The PUSH0 clone functions are intentionally postfixed with a jarring \"_PUSH0\" as\n/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.\n/// Please use with caution.\n///\n/// @dev Clones with immutable args (CWIA):\n/// The implementation of CWIA here implements a `receive()` method that emits the\n/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,\n/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards\n/// composability. The minimal proxy implementation does not offer this feature.\nlibrary LibClone {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Unable to deploy the clone.\n error DeploymentFailed();\n\n /// @dev The salt must start with either the zero address or the caller.\n error SaltDoesNotStartWithCaller();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MINIMAL PROXY OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a clone of `implementation`.\n function clone(address implementation) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * --------------------------------------------------------------------------+\n * CREATION (9 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * --------------------------------------------------------------------------|\n * RUNTIME (44 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * |\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | |\n * 3d | RETURNDATASIZE | 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 0 0 | |\n * |\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |\n * 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |\n * 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |\n * |\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\n * |\n * 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\n * |\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * --------------------------------------------------------------------------+\n */\n\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n instance := create(0, 0x0c, 0x35)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation` with `salt`.\n function cloneDeterministic(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n instance := create2(0, 0x0c, 0x35, salt)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Returns the initialization code hash of the clone of `implementation`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)\n mstore(0x14, implementation)\n mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)\n hash := keccak256(0x0c, 0x35)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x21, 0)\n }\n }\n\n /// @dev Returns the address of the deterministic clone of `implementation`,\n /// with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)\n internal\n pure\n returns (address predicted)\n {\n bytes32 hash = initCodeHash(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a PUSH0 clone of `implementation`.\n function clone_PUSH0(address implementation) internal returns (address instance) {\n /// @solidity memory-safe-assembly\n assembly {\n /**\n * --------------------------------------------------------------------------+\n * CREATION (9 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * 60 runSize | PUSH1 runSize | r | |\n * 5f | PUSH0 | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 5f | PUSH0 | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * --------------------------------------------------------------------------|\n * RUNTIME (45 bytes) |\n * --------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * --------------------------------------------------------------------------|\n * |\n * ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |\n * 5f | PUSH0 | 0 | |\n * 5f | PUSH0 | 0 0 | |\n * |\n * ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 | |\n * 5f | PUSH0 | 0 cds 0 0 | |\n * 5f | PUSH0 | 0 0 cds 0 0 | |\n * 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |\n * |\n * ::: delegate call to the implementation contract :::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |\n * 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |\n * 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |\n * 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |\n * f4 | DELEGATECALL | success | [0..cds): calldata |\n * |\n * ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success | [0..cds): calldata |\n * 5f | PUSH0 | 0 rds success | [0..cds): calldata |\n * 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |\n * 3e | RETURNDATACOPY | success | [0..rds): returndata |\n * |\n * 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |\n * 57 | JUMPI | | [0..rds): returndata |\n * |\n * ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | | [0..rds): returndata |\n * 3d | RETURNDATASIZE | rds | [0..rds): returndata |\n * 5f | PUSH0 | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * --------------------------------------------------------------------------+\n */\n\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n instance := create(0, 0x0e, 0x36)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.\n function cloneDeterministic_PUSH0(address implementation, bytes32 salt)\n internal\n returns (address instance)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n instance := create2(0, 0x0e, 0x36, salt)\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16\n mstore(0x14, implementation) // 20\n mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9\n hash := keccak256(0x0e, 0x36)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x24, 0)\n }\n }\n\n /// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,\n /// with `salt` by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress_PUSH0(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHash_PUSH0(implementation);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CLONES WITH IMMUTABLE ARGS OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Deploys a minimal proxy with `implementation`,\n /// using immutable arguments encoded in `data`.\n ///\n /// Note: This implementation of CWIA differs from the original implementation.\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\n function clone(address implementation, bytes memory data) internal returns (address instance) {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n // The `creationSize` is `extraLength + 108`\n // The `runSize` is `creationSize - 10`.\n\n /**\n * ---------------------------------------------------------------------------------------------------+\n * CREATION (10 bytes) |\n * ---------------------------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------------------------|\n * 61 runSize | PUSH2 runSize | r | |\n * 3d | RETURNDATASIZE | 0 r | |\n * 81 | DUP2 | r 0 r | |\n * 60 offset | PUSH1 offset | o r 0 r | |\n * 3d | RETURNDATASIZE | 0 o r 0 r | |\n * 39 | CODECOPY | 0 r | [0..runSize): runtime code |\n * f3 | RETURN | | [0..runSize): runtime code |\n * ---------------------------------------------------------------------------------------------------|\n * RUNTIME (98 bytes + extraLength) |\n * ---------------------------------------------------------------------------------------------------|\n * Opcode | Mnemonic | Stack | Memory |\n * ---------------------------------------------------------------------------------------------------|\n * |\n * ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 60 0x2c | PUSH1 0x2c | 0x2c cds | |\n * 57 | JUMPI | | |\n * 34 | CALLVALUE | cv | |\n * 3d | RETURNDATASIZE | 0 cv | |\n * 52 | MSTORE | | [0..0x20): callvalue |\n * 7f sig | PUSH32 0x9e.. | sig | [0..0x20): callvalue |\n * 59 | MSIZE | 0x20 sig | [0..0x20): callvalue |\n * 3d | RETURNDATASIZE | 0 0x20 sig | [0..0x20): callvalue |\n * a1 | LOG1 | | [0..0x20): callvalue |\n * 00 | STOP | | [0..0x20): callvalue |\n * 5b | JUMPDEST | | |\n * |\n * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds | |\n * 3d | RETURNDATASIZE | 0 cds | |\n * 3d | RETURNDATASIZE | 0 0 cds | |\n * 37 | CALLDATACOPY | | [0..cds): calldata |\n * |\n * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |\n * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata |\n * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata |\n * |\n * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata |\n * 60 0x62 | PUSH1 0x62 | 0x62 e e 0 0 0 0 | [0..cds): calldata |\n * 36 | CALLDATASIZE | cds 0x62 e e 0 0 0 0 | [0..cds): calldata |\n * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * |\n * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * |\n * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |\n * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\n * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |\n * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |\n * |\n * 60 0x60 | PUSH1 0x60 | 0x60 success 0 rds | [0..rds): returndata |\n * 57 | JUMPI | 0 rds | [0..rds): returndata |\n * |\n * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * fd | REVERT | | [0..rds): returndata |\n * |\n * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |\n * 5b | JUMPDEST | 0 rds | [0..rds): returndata |\n * f3 | RETURN | | [0..rds): returndata |\n * ---------------------------------------------------------------------------------------------------+\n */\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\n // The actual EVM limit may be smaller and may change over time.\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Create the instance.\n instance := create(0, sub(data, 0x4c), add(extraLength, 0x6c))\n\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Deploys a deterministic clone of `implementation`,\n /// using immutable arguments encoded in `data`, with `salt`.\n ///\n /// Note: This implementation of CWIA differs from the original implementation.\n /// If the calldata is empty, it will emit a `ReceiveETH(uint256)` event and skip the `DELEGATECALL`.\n function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)\n internal\n returns (address instance)\n {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n // Do a out-of-gas revert if `extraLength` is too big. 0xffff - 0x62 + 0x01 = 0xff9e.\n // The actual EVM limit may be smaller and may change over time.\n sub(data, add(0x59, lt(extraLength, 0xff9e))),\n or(shl(0x78, add(extraLength, 0x62)), 0xfd6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Create the instance.\n instance := create2(0, sub(data, 0x4c), add(extraLength, 0x6c), salt)\n\n // If `instance` is zero, revert.\n if iszero(instance) {\n // Store the function selector of `DeploymentFailed()`.\n mstore(0x00, 0x30116425)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Returns the initialization code hash of the clone of `implementation`\n /// using immutable arguments encoded in `data`.\n /// Used for mining vanity addresses with create2crunch.\n function initCodeHash(address implementation, bytes memory data)\n internal\n pure\n returns (bytes32 hash)\n {\n assembly {\n // Compute the boundaries of the data and cache the memory slots around it.\n let mBefore3 := mload(sub(data, 0x60))\n let mBefore2 := mload(sub(data, 0x40))\n let mBefore1 := mload(sub(data, 0x20))\n let dataLength := mload(data)\n let dataEnd := add(add(data, 0x20), dataLength)\n let mAfter1 := mload(dataEnd)\n\n // Do a out-of-gas revert if `dataLength` is too big. 0xffff - 0x02 - 0x62 = 0xff9b.\n // The actual EVM limit may be smaller and may change over time.\n returndatacopy(returndatasize(), returndatasize(), gt(dataLength, 0xff9b))\n\n // +2 bytes for telling how much data there is appended to the call.\n let extraLength := add(dataLength, 2)\n\n // Write the bytecode before the data.\n mstore(data, 0x5af43d3d93803e606057fd5bf3)\n // Write the address of the implementation.\n mstore(sub(data, 0x0d), implementation)\n // Write the rest of the bytecode.\n mstore(\n sub(data, 0x21),\n or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)\n )\n // `keccak256(\"ReceiveETH(uint256)\")`\n mstore(\n sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff\n )\n mstore(\n sub(data, 0x5a),\n or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)\n )\n mstore(dataEnd, shl(0xf0, extraLength))\n\n // Compute and store the bytecode hash.\n hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))\n\n // Restore the overwritten memory surrounding `data`.\n mstore(dataEnd, mAfter1)\n mstore(data, dataLength)\n mstore(sub(data, 0x20), mBefore1)\n mstore(sub(data, 0x40), mBefore2)\n mstore(sub(data, 0x60), mBefore3)\n }\n }\n\n /// @dev Returns the address of the deterministic clone of\n /// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(\n address implementation,\n bytes memory data,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n bytes32 hash = initCodeHash(implementation, data);\n predicted = predictDeterministicAddress(hash, salt, deployer);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* OTHER OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns the address when a contract with initialization code hash,\n /// `hash`, is deployed with `salt`, by `deployer`.\n /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)\n internal\n pure\n returns (address predicted)\n {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and store the bytecode hash.\n mstore8(0x00, 0xff) // Write the prefix.\n mstore(0x35, hash)\n mstore(0x01, shl(96, deployer))\n mstore(0x15, salt)\n predicted := keccak256(0x00, 0x55)\n // Restore the part of the free memory pointer that has been overwritten.\n mstore(0x35, 0)\n }\n }\n\n /// @dev Reverts if `salt` does not start with either the zero address or the caller.\n function checkStartsWithCaller(bytes32 salt) internal view {\n /// @solidity memory-safe-assembly\n assembly {\n // If the salt does not start with the zero address or the caller.\n if iszero(or(iszero(shr(96, salt)), eq(caller(), shr(96, salt)))) {\n // Store the function selector of `SaltDoesNotStartWithCaller()`.\n mstore(0x00, 0x2f634836)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n }\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file