diff --git a/deploy/deploy.js b/deploy/deploy.js index 914588c..3121293 100644 --- a/deploy/deploy.js +++ b/deploy/deploy.js @@ -4,18 +4,9 @@ const deploy = async (hre) => { } = hre; const [deployer] = await hre.ethers.getSigners(); - const wrapperFCLWebAuthn = await deploy("WrapperFCLWebAuthn", { - from: deployer.address, - log: true, - deterministicDeployment: true, - }); - const P256Signer = await deploy("P256Signer", { from: deployer.address, log: true, - libraries: { - WrapperFCLWebAuthn: wrapperFCLWebAuthn.address, - }, deterministicDeployment: true, }); @@ -26,13 +17,9 @@ const deploy = async (hre) => { args: [P256Signer.address], }); - await run("verify:verify", { address: wrapperFCLWebAuthn.address }); - await run("verify:verify", { + /* await run("verify:verify", { address: P256Signer.address, - libraries: { - WrapperFCLWebAuthn: wrapperFCLWebAuthn.address, - }, - }); + }); */ await run("verify:verify", { address: factory.address, constructorArguments: [P256Signer.address], diff --git a/deployments/avalanche/P256Signer.json b/deployments/avalanche/P256Signer.json index c5e4697..d703bfe 100644 --- a/deployments/avalanche/P256Signer.json +++ b/deployments/avalanche/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8", + "address": "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0x00c7a9582e39d7e4549b5ff30c0c2ec172ce1efeb2bcc2a495708caf44f4c6ce", + "transactionHash": "0xb1d7c6917d7c770b9d8b7db363cdc118addf170f20a9b59f923e1c2b75095f0b", "receipt": { "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", - "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "from": "0xda677C8877E49Dfc31dC7e92fA7615F4Fb4047D7", "contractAddress": null, - "transactionIndex": 49, - "gasUsed": "502749", + "transactionIndex": 8, + "gasUsed": "1841285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0e5196e3ad46fea05826dcd7843384ee29ed63ea52d090dc8b1600dedfdea36f", - "transactionHash": "0x00c7a9582e39d7e4549b5ff30c0c2ec172ce1efeb2bcc2a495708caf44f4c6ce", + "blockHash": "0x5d110c6f3ab69f75c593842550e049e4b5bf0b375063d2c8f1a95c85156be620", + "transactionHash": "0xb1d7c6917d7c770b9d8b7db363cdc118addf170f20a9b59f923e1c2b75095f0b", "logs": [], - "blockNumber": 39203620, - "cumulativeGasUsed": "1736504", + "blockNumber": 39962044, + "cumulativeGasUsed": "4555284", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073B15bb4dE71bF6fbB91913872dB9F18E6C8897E9F630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xB15bb4dE71bF6fbB91913872dB9F18E6C8897E9F" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/avalanche/P256SignerFactory.json b/deployments/avalanche/P256SignerFactory.json index 2296e44..758ede0 100644 --- a/deployments/avalanche/P256SignerFactory.json +++ b/deployments/avalanche/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x8072CB92Bd6EF882683cAaC8F28985F216ae9d6f", + "address": "0x841Da89727BB8c0807738230e3781D07b659653D", "abi": [ { "inputs": [ @@ -75,30 +75,30 @@ "type": "function" } ], - "transactionHash": "0x6b79999a0e274c565aafb54557ac779e65dd53670d2c816a81839059a97109fe", + "transactionHash": "0xab758594148b6c9aaeee48d7722099445863a9efda4d22bb64cc42da590e7be9", "receipt": { "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", - "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "from": "0xda677C8877E49Dfc31dC7e92fA7615F4Fb4047D7", "contractAddress": null, - "transactionIndex": 68, + "transactionIndex": 3, "gasUsed": "195400", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xee4565412f82e7209100b53344e87d524bd564fcdf0793b589e51ccc3aa5ddb9", - "transactionHash": "0x6b79999a0e274c565aafb54557ac779e65dd53670d2c816a81839059a97109fe", + "blockHash": "0x2fe25502eec6360a490bbcbaf5b6c394fdbb0683553358272031bed087ae7be9", + "transactionHash": "0xab758594148b6c9aaeee48d7722099445863a9efda4d22bb64cc42da590e7be9", "logs": [], - "blockNumber": 39203718, - "cumulativeGasUsed": "2344443", + "blockNumber": 39962047, + "cumulativeGasUsed": "342156", "status": 1, "byzantium": true }, "args": [ - "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8" + "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/avalanche/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/avalanche/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/avalanche/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/avalanche_production/P256Signer.json b/deployments/avalanche_production/P256Signer.json index c051219..50c5e26 100644 --- a/deployments/avalanche_production/P256Signer.json +++ b/deployments/avalanche_production/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8", + "address": "0x71558e9Ac314B17Eb665441aFF60914EAE391712", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0x836d9d0bad8797545855b64da1817276118434bab7fe04a35f0c709983036bee", + "transactionHash": "0x89b4e7583591ccf959c82e2695528c5a715fd858b252a0437a6d75ed58b3d67e", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", - "from": "0x53011E110CAd8685F4911508B4E2413f526Df73E", + "from": "0xda677C8877E49Dfc31dC7e92fA7615F4Fb4047D7", "contractAddress": null, - "transactionIndex": 79, - "gasUsed": "502749", + "transactionIndex": 4, + "gasUsed": "1841285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3b6c4b37c4fa0ace4494b0cb2ecb5d6dc43b7543d18dcb5504614d7960286fd4", - "transactionHash": "0x836d9d0bad8797545855b64da1817276118434bab7fe04a35f0c709983036bee", + "blockHash": "0xeffe6da715f36435b183b4ac5191c83b9c5a2244e64ddf4ee5aadfab78c837e5", + "transactionHash": "0x89b4e7583591ccf959c82e2695528c5a715fd858b252a0437a6d75ed58b3d67e", "logs": [], - "blockNumber": 39253077, - "cumulativeGasUsed": "2446060", + "blockNumber": 39962645, + "cumulativeGasUsed": "2117985", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b935093509350935060007321D84679F9dd3f0e4914a806113CF329368d5253630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0x21D84679F9dd3f0e4914a806113CF329368d5253" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/avalanche_production/P256SignerFactory.json b/deployments/avalanche_production/P256SignerFactory.json index 19a1380..321accc 100644 --- a/deployments/avalanche_production/P256SignerFactory.json +++ b/deployments/avalanche_production/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x432870e7E5DBB4dF79f92aD0FA0FeF10f3b71219", + "address": "0x73dA77F0f2daaa88b908413495d3D0e37458212e", "abi": [ { "inputs": [ @@ -75,30 +75,30 @@ "type": "function" } ], - "transactionHash": "0x9c45413215eb15e39fc8246d438deb9c4f0855e2558f4aae2873df1ea6698a2e", + "transactionHash": "0x5b37e5f86aa7c6edabcdc2e22c485e4b4932a386d8ca61e951628e18de5df95f", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", - "from": "0x53011E110CAd8685F4911508B4E2413f526Df73E", + "from": "0xda677C8877E49Dfc31dC7e92fA7615F4Fb4047D7", "contractAddress": null, - "transactionIndex": 63, + "transactionIndex": 6, "gasUsed": "195400", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x621ff5b90a41c9a2e2984ba32fc1d6d76829f22e9d1c2d54f52826c2fa9f8fd9", - "transactionHash": "0x9c45413215eb15e39fc8246d438deb9c4f0855e2558f4aae2873df1ea6698a2e", + "blockHash": "0xbaf9e1d098a32c50defb7865accc76600b2b9f4968b8256545c0a17590738dc3", + "transactionHash": "0x5b37e5f86aa7c6edabcdc2e22c485e4b4932a386d8ca61e951628e18de5df95f", "logs": [], - "blockNumber": 39253121, - "cumulativeGasUsed": "1668857", + "blockNumber": 39962648, + "cumulativeGasUsed": "1249776", "status": 1, "byzantium": true }, "args": [ - "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8" + "0x71558e9Ac314B17Eb665441aFF60914EAE391712" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/avalanche_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/avalanche_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/avalanche_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/chiado/.pendingTransactions b/deployments/chiado/.pendingTransactions new file mode 100644 index 0000000..b1d161e --- /dev/null +++ b/deployments/chiado/.pendingTransactions @@ -0,0 +1,18 @@ +{ + "0xa9f1b3cf00057992b22b6cd14d216c575eeb2fddc3ba8d318379f59f382ae8db": { + "decoded": { + "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "maxFeePerGas": "10000001", + "maxPriorityFeePerGas": "9999993", + "gasLimit": "1868384", + "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", + "value": "0", + "nonce": 6, + "data": "0x0000000000000000000000000000000000000000000000000000000000000000608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "r": "0x83a7e8b62b69b6f7bbe74f07e9b76a703e71b69e1adb8282a2b60798dbd675f4", + "s": "0x4e2d85463a917f6c219d84a5b80170a6b1553c041b4172570ed59c245ce2cf99", + "v": 0, + "chainId": 10200 + } + } +} \ No newline at end of file diff --git a/deployments/chiado/P256Signer.json b/deployments/chiado/P256Signer.json index 82f194a..7307319 100644 --- a/deployments/chiado/P256Signer.json +++ b/deployments/chiado/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8", + "address": "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,12 @@ "type": "function" } ], - "transactionHash": "0xc6b1a12f7125038d06ecdb74ea289b10acee1a6fce966306912087ad897d4859", - "receipt": { - "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", - "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "502877", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x96554234f7adfeaa1811e31740e23ea3ebe71ce1a4b056978af2fd3910b38f17", - "transactionHash": "0xc6b1a12f7125038d06ecdb74ea289b10acee1a6fce966306912087ad897d4859", - "logs": [], - "blockNumber": 7411487, - "cumulativeGasUsed": "854139", - "status": 1, - "byzantium": true - }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073B15bb4dE71bF6fbB91913872dB9F18E6C8897E9F630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xB15bb4dE71bF6fbB91913872dB9F18E6C8897E9F" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +219,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +227,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +235,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/chiado/P256SignerFactory.json b/deployments/chiado/P256SignerFactory.json index ece5f03..4170638 100644 --- a/deployments/chiado/P256SignerFactory.json +++ b/deployments/chiado/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x8072CB92Bd6EF882683cAaC8F28985F216ae9d6f", + "address": "0x841Da89727BB8c0807738230e3781D07b659653D", "abi": [ { "inputs": [ @@ -75,30 +75,30 @@ "type": "function" } ], - "transactionHash": "0x9dc1c869ff075d38d880e33247b87cc0514bfb6af8ce926a7d2597e4f35c0791", + "transactionHash": "0xce0e812708de1cd2777183978505f7ff0cf00f1b5e399d54433c5d974208463b", "receipt": { "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 3, + "transactionIndex": 0, "gasUsed": "195452", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x73c56f7ae7d01153bf262df8770582ce1fa049b5957331be66100b26de137855", - "transactionHash": "0x9dc1c869ff075d38d880e33247b87cc0514bfb6af8ce926a7d2597e4f35c0791", + "blockHash": "0xedf230aeb4c3d7a14a7fe740b4a4246d53f84d45e0630b8278a3d90441a4fe92", + "transactionHash": "0xce0e812708de1cd2777183978505f7ff0cf00f1b5e399d54433c5d974208463b", "logs": [], - "blockNumber": 7411490, - "cumulativeGasUsed": "334658", + "blockNumber": 7661483, + "cumulativeGasUsed": "195452", "status": 1, "byzantium": true }, "args": [ - "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8" + "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/chiado/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/chiado/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/chiado/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/chiado_production/P256Signer.json b/deployments/chiado_production/P256Signer.json index 995bac2..1b4db95 100644 --- a/deployments/chiado_production/P256Signer.json +++ b/deployments/chiado_production/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8", + "address": "0x71558e9Ac314B17Eb665441aFF60914EAE391712", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,12 @@ "type": "function" } ], - "transactionHash": "0x2808c5bbe5cbe94bd6993ea20f3f9c026e101260da3dae84e5db527c196c4e5b", - "receipt": { - "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", - "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "502877", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7b8e7e9ebf8e45bd95cb100fc7858fd6dd5ad4c81d117c88ea4038d42fde8556", - "transactionHash": "0x2808c5bbe5cbe94bd6993ea20f3f9c026e101260da3dae84e5db527c196c4e5b", - "logs": [], - "blockNumber": 7426546, - "cumulativeGasUsed": "502877", - "status": 1, - "byzantium": true - }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b935093509350935060007321D84679F9dd3f0e4914a806113CF329368d5253630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0x21D84679F9dd3f0e4914a806113CF329368d5253" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +219,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +227,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +235,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/chiado_production/P256SignerFactory.json b/deployments/chiado_production/P256SignerFactory.json index 2c8b861..67e50ee 100644 --- a/deployments/chiado_production/P256SignerFactory.json +++ b/deployments/chiado_production/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x432870e7E5DBB4dF79f92aD0FA0FeF10f3b71219", + "address": "0x73dA77F0f2daaa88b908413495d3D0e37458212e", "abi": [ { "inputs": [ @@ -75,30 +75,30 @@ "type": "function" } ], - "transactionHash": "0xb0a84207bf384a4afcad7b2ed5a1b70d557be968ca2a495f5f76f459c225e65a", + "transactionHash": "0x10a12e83a0c66866e6709cba90a72a731779393a3687b478290fdd14b30db6de", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 10, + "transactionIndex": 0, "gasUsed": "195452", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x66884b13b046c6a86ed027721f7297f043367eb3ad675182341762a4d0352fae", - "transactionHash": "0xb0a84207bf384a4afcad7b2ed5a1b70d557be968ca2a495f5f76f459c225e65a", + "blockHash": "0xbc9fd03642f7390996cccbad5c16fc133282e9f8f1306fc071713e134869a0a3", + "transactionHash": "0x10a12e83a0c66866e6709cba90a72a731779393a3687b478290fdd14b30db6de", "logs": [], - "blockNumber": 7426548, - "cumulativeGasUsed": "963796", + "blockNumber": 7661670, + "cumulativeGasUsed": "195452", "status": 1, "byzantium": true }, "args": [ - "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8" + "0x71558e9Ac314B17Eb665441aFF60914EAE391712" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/chiado_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/chiado_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/chiado_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/fuji/P256Signer.json b/deployments/fuji/P256Signer.json index bf34622..91e6ddd 100644 --- a/deployments/fuji/P256Signer.json +++ b/deployments/fuji/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8", + "address": "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0x75f57d8a45f621b442a160dbb807a7ffa05189078dea8541495c78810f5f2a6c", + "transactionHash": "0x7db8e0627af4b3e6aa265fb94f2f4fdae4755bdb78d9c2fd48bbadca26ba8fac", "receipt": { "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "502749", + "transactionIndex": 0, + "gasUsed": "1841285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x63f151719f4da58b9bb05ec33bc3e7bf5a9ec33b63f0473e238d38c5ac333d93", - "transactionHash": "0x75f57d8a45f621b442a160dbb807a7ffa05189078dea8541495c78810f5f2a6c", + "blockHash": "0x7484928c7f5d47c7c102270573201465b52819a09b12af08e56214dbedcad439", + "transactionHash": "0x7db8e0627af4b3e6aa265fb94f2f4fdae4755bdb78d9c2fd48bbadca26ba8fac", "logs": [], - "blockNumber": 28654654, - "cumulativeGasUsed": "560595", + "blockNumber": 29082804, + "cumulativeGasUsed": "1841285", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073B15bb4dE71bF6fbB91913872dB9F18E6C8897E9F630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xB15bb4dE71bF6fbB91913872dB9F18E6C8897E9F" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/fuji/P256SignerFactory.json b/deployments/fuji/P256SignerFactory.json index d182638..2d3819a 100644 --- a/deployments/fuji/P256SignerFactory.json +++ b/deployments/fuji/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x8072CB92Bd6EF882683cAaC8F28985F216ae9d6f", + "address": "0x841Da89727BB8c0807738230e3781D07b659653D", "abi": [ { "inputs": [ @@ -75,7 +75,7 @@ "type": "function" } ], - "transactionHash": "0xf9d9a2580ab6e329239841bc58a8430816da261274d3e9c0bf1ac22981f82f40", + "transactionHash": "0xfe18a30260a23ab997ef29bccfb98247e1182275d51dd5eb75119c3cddbb1034", "receipt": { "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", @@ -83,22 +83,22 @@ "transactionIndex": 0, "gasUsed": "195400", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf1d854d731fb307c1ba4e86847b49e9ca48562c07b25dc64e22863a75aa10cc9", - "transactionHash": "0xf9d9a2580ab6e329239841bc58a8430816da261274d3e9c0bf1ac22981f82f40", + "blockHash": "0xe18517acd495bee6fa705f745dae1eecf719d03204ce9e057115d0af9ba4f70e", + "transactionHash": "0xfe18a30260a23ab997ef29bccfb98247e1182275d51dd5eb75119c3cddbb1034", "logs": [], - "blockNumber": 28654656, + "blockNumber": 29082807, "cumulativeGasUsed": "195400", "status": 1, "byzantium": true }, "args": [ - "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8" + "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/fuji/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/fuji/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/fuji/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/fuji_production/P256Signer.json b/deployments/fuji_production/P256Signer.json index b35f4d4..1b3bacf 100644 --- a/deployments/fuji_production/P256Signer.json +++ b/deployments/fuji_production/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8", + "address": "0x71558e9Ac314B17Eb665441aFF60914EAE391712", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0x45a77bfd9046f379819b7b6e6e9fcc8a01248d1407b846e49cad748c33c3401a", + "transactionHash": "0x5cfa49daf9b842a3e35ec54fbf017bc91c40ca5cf92404aeba6b2c74241815a5", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "502749", + "transactionIndex": 0, + "gasUsed": "1841285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x05ae86a22e87ec29f496179737dfa13fb2d51e1ea675ebfe673af0f1af2188c1", - "transactionHash": "0x45a77bfd9046f379819b7b6e6e9fcc8a01248d1407b846e49cad748c33c3401a", + "blockHash": "0xea758d1d936da90f28f5a15a4e00f102c52600bcded2ebe861268b7cfb516dca", + "transactionHash": "0x5cfa49daf9b842a3e35ec54fbf017bc91c40ca5cf92404aeba6b2c74241815a5", "logs": [], - "blockNumber": 28682453, - "cumulativeGasUsed": "895002", + "blockNumber": 29083171, + "cumulativeGasUsed": "1841285", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b935093509350935060007321D84679F9dd3f0e4914a806113CF329368d5253630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0x21D84679F9dd3f0e4914a806113CF329368d5253" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/fuji_production/P256SignerFactory.json b/deployments/fuji_production/P256SignerFactory.json index 5dc3e78..43d967d 100644 --- a/deployments/fuji_production/P256SignerFactory.json +++ b/deployments/fuji_production/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x432870e7E5DBB4dF79f92aD0FA0FeF10f3b71219", + "address": "0x73dA77F0f2daaa88b908413495d3D0e37458212e", "abi": [ { "inputs": [ @@ -75,7 +75,7 @@ "type": "function" } ], - "transactionHash": "0x906a04d1c97212e54f0586c3a044cb610046704e03da0c211ad0e50b70d81443", + "transactionHash": "0x719c96f275c1aa727ffaf266183cbceb9e01ae024f6d0adb24cd6c6f79258f83", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", @@ -83,22 +83,22 @@ "transactionIndex": 0, "gasUsed": "195400", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7815e4dcbf359625f7a549c3ca13462a58d8bfa92c848c6532debb83fdc79bd2", - "transactionHash": "0x906a04d1c97212e54f0586c3a044cb610046704e03da0c211ad0e50b70d81443", + "blockHash": "0xf3091de0ccd2ebc1d4810af50745a4810b488e49042ebdf09ea96be8c352e42a", + "transactionHash": "0x719c96f275c1aa727ffaf266183cbceb9e01ae024f6d0adb24cd6c6f79258f83", "logs": [], - "blockNumber": 28682455, + "blockNumber": 29083174, "cumulativeGasUsed": "195400", "status": 1, "byzantium": true }, "args": [ - "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8" + "0x71558e9Ac314B17Eb665441aFF60914EAE391712" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/fuji_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/fuji_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/fuji_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/gnosischain/P256Signer.json b/deployments/gnosischain/P256Signer.json index b592821..c438934 100644 --- a/deployments/gnosischain/P256Signer.json +++ b/deployments/gnosischain/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8", + "address": "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,15 +137,28 @@ "type": "function" } ], - "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xB15bb4dE71bF6fbB91913872dB9F18E6C8897E9F" + "transactionHash": "0x363ae714ac585ae77a093955e6c726d9afc0c4d7f2b737c5b6b5f1b30c03011b", + "receipt": { + "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", + "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "contractAddress": null, + "transactionIndex": 44, + "gasUsed": "1841805", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbe4c260e3811f8f1b85a3d45b4df16d9e5bbc3a8b752daea27f8a99dcd369099", + "transactionHash": "0x363ae714ac585ae77a093955e6c726d9afc0c4d7f2b737c5b6b5f1b30c03011b", + "logs": [], + "blockNumber": 31794791, + "cumulativeGasUsed": "15368663", + "status": 1, + "byzantium": true }, + "args": [], + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -212,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -220,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -228,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/gnosischain/P256SignerFactory.json b/deployments/gnosischain/P256SignerFactory.json index a87bd34..cef455e 100644 --- a/deployments/gnosischain/P256SignerFactory.json +++ b/deployments/gnosischain/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x8072CB92Bd6EF882683cAaC8F28985F216ae9d6f", + "address": "0x841Da89727BB8c0807738230e3781D07b659653D", "abi": [ { "inputs": [ @@ -75,14 +75,30 @@ "type": "function" } ], + "transactionHash": "0x77f35334941d0b3ab78deed1241284e20da413f8eb9e858d5b63dd1a4ac85864", + "receipt": { + "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", + "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "contractAddress": null, + "transactionIndex": 1, + "gasUsed": "195452", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x97e7a464a7e7cbcac56b8b766a58b2d7b34866f2bb306a60cc7be59e5fed6bef", + "transactionHash": "0x77f35334941d0b3ab78deed1241284e20da413f8eb9e858d5b63dd1a4ac85864", + "logs": [], + "blockNumber": 31794793, + "cumulativeGasUsed": "395599", + "status": 1, + "byzantium": true + }, "args": [ - "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8" + "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503" ], - "numDeployments": 3, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 4, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/gnosischain/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/gnosischain/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/gnosischain/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/gnosischain_production/P256Signer.json b/deployments/gnosischain_production/P256Signer.json index a5410c8..a596cad 100644 --- a/deployments/gnosischain_production/P256Signer.json +++ b/deployments/gnosischain_production/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8", + "address": "0x71558e9Ac314B17Eb665441aFF60914EAE391712", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0x5d3cb53a8aba607c594df7ba8de8ed095ae42ead5bcef798f6855b5009d5eea1", + "transactionHash": "0x9edef32f19be190ea49789ffa64aa8a9152d24c437395ece5f3a0fda620faea3", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 2, - "gasUsed": "502877", + "transactionIndex": 19, + "gasUsed": "1841805", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa04e91577b96fd84ca9ae2ad9880117aac33d6b64b79b4b170217bc6fc08c652", - "transactionHash": "0x5d3cb53a8aba607c594df7ba8de8ed095ae42ead5bcef798f6855b5009d5eea1", + "blockHash": "0x25241522cd5ca68aa447a384a473b7452186d293836c718abdc26684c813b01a", + "transactionHash": "0x9edef32f19be190ea49789ffa64aa8a9152d24c437395ece5f3a0fda620faea3", "logs": [], - "blockNumber": 31519773, - "cumulativeGasUsed": "1003678", + "blockNumber": 31795011, + "cumulativeGasUsed": "3747040", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b935093509350935060007321D84679F9dd3f0e4914a806113CF329368d5253630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0x21D84679F9dd3f0e4914a806113CF329368d5253" - }, + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/gnosischain_production/P256SignerFactory.json b/deployments/gnosischain_production/P256SignerFactory.json index 9c24160..002d5c2 100644 --- a/deployments/gnosischain_production/P256SignerFactory.json +++ b/deployments/gnosischain_production/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x432870e7E5DBB4dF79f92aD0FA0FeF10f3b71219", + "address": "0x73dA77F0f2daaa88b908413495d3D0e37458212e", "abi": [ { "inputs": [ @@ -75,30 +75,45 @@ "type": "function" } ], - "transactionHash": "0x5546849b3674b65c30e64a331189d151523ffc55373a4a5496151084217be183", + "transactionHash": "0x6719288cad0a9039b2899bf6a4bb36bfb798655edd4b59e201d10874f91a2e0f", "receipt": { - "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", - "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "to": "0x7B794196F6D976c91e1a1b3d149CC403f2910A4a", + "from": "0xa97B9d563eC617f50fE511A919244Fc3AFa8B24e", "contractAddress": null, - "transactionIndex": 3, - "gasUsed": "195452", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x8d038c7f9d1ca9ee9a763572e5e4b19ccccb305beca3c34ead217b7c74c6956a", - "transactionHash": "0x5546849b3674b65c30e64a331189d151523ffc55373a4a5496151084217be183", - "logs": [], - "blockNumber": 31519775, - "cumulativeGasUsed": "7004503", + "transactionIndex": 0, + "gasUsed": "141066", + "logsBloom": "0x00000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000400000000000200000000000000000001000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000100000000000002000000000000000000000000000000000000000000000080000000000000200000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xb7b214dff0430aedb1d0655d5aeb4bd56f9d74192468a7bdbf90bf4b40718c2f", + "transactionHash": "0x6719288cad0a9039b2899bf6a4bb36bfb798655edd4b59e201d10874f91a2e0f", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 25088388, + "transactionHash": "0xcefa46c6bd74de001586c6f3bd9ab22c96e979c524d3ff4055a54ae89e18504c", + "address": "0x51eaDb3E5Fa505f83bf76cEF62d7FE7050248Adb", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000007b794196f6d976c91e1a1b3d149cc403f2910a4a", + "0x000000000000000000000000aabdbb53129b2d486a82cd3218f20a8b2fb1e360" + ], + "data": "0x0000000000000000000000000000000000000000000000a451ca595f43393a84", + "logIndex": 0, + "blockHash": "0xb7b214dff0430aedb1d0655d5aeb4bd56f9d74192468a7bdbf90bf4b40718c2f" + } + ], + "blockNumber": 25088388, + "cumulativeGasUsed": "141066", "status": 1, "byzantium": true }, "args": [ - "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8" + "0x71558e9Ac314B17Eb665441aFF60914EAE391712" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/gnosischain_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/gnosischain_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/gnosischain_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/mumbai/P256Signer.json b/deployments/mumbai/P256Signer.json index b592821..8219205 100644 --- a/deployments/mumbai/P256Signer.json +++ b/deployments/mumbai/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8", + "address": "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,15 +137,44 @@ "type": "function" } ], - "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xB15bb4dE71bF6fbB91913872dB9F18E6C8897E9F" + "transactionHash": "0xe61293d34714f21418b342cf16199bedff42403a2ae0ff30b786069a72f12e0c", + "receipt": { + "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", + "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "contractAddress": null, + "transactionIndex": 2, + "gasUsed": "1841805", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000020000000000000002010000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000080000000000000000000000000000000000000000000100000", + "blockHash": "0x9e2134541c92a8e37d7d44c5c6fb71a8ee024435e05449822d2fb925528540d9", + "transactionHash": "0xe61293d34714f21418b342cf16199bedff42403a2ae0ff30b786069a72f12e0c", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 44418662, + "transactionHash": "0xe61293d34714f21418b342cf16199bedff42403a2ae0ff30b786069a72f12e0c", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", + "0x0000000000000000000000005082f249cdb2f2c1ee035e4f423c46ea2dab3ab1" + ], + "data": "0x000000000000000000000000000000000000000000000000001776019b7edc89000000000000000000000000000000000000000000000000009695c7d2adb93e0000000000000000000000000000000000000000000004f2f5b7fcea76a8809a000000000000000000000000000000000000000000000000007f1fc6372edcb50000000000000000000000000000000000000000000004f2f5cf72ec12275d23", + "logIndex": 3, + "blockHash": "0x9e2134541c92a8e37d7d44c5c6fb71a8ee024435e05449822d2fb925528540d9" + } + ], + "blockNumber": 44418662, + "cumulativeGasUsed": "2024335", + "status": 1, + "byzantium": true }, + "args": [], + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -212,7 +251,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -220,7 +259,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -228,7 +267,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/mumbai/P256SignerFactory.json b/deployments/mumbai/P256SignerFactory.json index 0e6141c..d99bbc8 100644 --- a/deployments/mumbai/P256SignerFactory.json +++ b/deployments/mumbai/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x8072CB92Bd6EF882683cAaC8F28985F216ae9d6f", + "address": "0x841Da89727BB8c0807738230e3781D07b659653D", "abi": [ { "inputs": [ @@ -75,14 +75,46 @@ "type": "function" } ], + "transactionHash": "0x97a766dbf72b87c0bbbc57d91e929a3ac0866f1982f5e0eb72d3eff775d193cc", + "receipt": { + "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", + "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "contractAddress": null, + "transactionIndex": 4, + "gasUsed": "195452", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000020000000000000002010000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000080000000000000000000000000000000000000000000100000", + "blockHash": "0x55e27d81060cb3fcb198403fb5251e807306be67c574ffcbc68b08e800777fcf", + "transactionHash": "0x97a766dbf72b87c0bbbc57d91e929a3ac0866f1982f5e0eb72d3eff775d193cc", + "logs": [ + { + "transactionIndex": 4, + "blockNumber": 44418665, + "transactionHash": "0x97a766dbf72b87c0bbbc57d91e929a3ac0866f1982f5e0eb72d3eff775d193cc", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", + "0x0000000000000000000000005082f249cdb2f2c1ee035e4f423c46ea2dab3ab1" + ], + "data": "0x000000000000000000000000000000000000000000000000000244ef1859bfc4000000000000000000000000000000000000000000000000007f1fc635894e720000000000000000000000000000000000000000000004f2f62d2511fbb895a0000000000000000000000000000000000000000000000000007cdad71d2f8eae0000000000000000000000000000000000000000000004f2f62f6a0114125564", + "logIndex": 14, + "blockHash": "0x55e27d81060cb3fcb198403fb5251e807306be67c574ffcbc68b08e800777fcf" + } + ], + "blockNumber": 44418665, + "cumulativeGasUsed": "729820", + "status": 1, + "byzantium": true + }, "args": [ - "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8" + "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503" ], - "numDeployments": 4, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 5, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/mumbai/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/mumbai/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/mumbai/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/mumbai_production/P256Signer.json b/deployments/mumbai_production/P256Signer.json index 7f9b30c..ec7978a 100644 --- a/deployments/mumbai_production/P256Signer.json +++ b/deployments/mumbai_production/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8", + "address": "0x71558e9Ac314B17Eb665441aFF60914EAE391712", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,47 +137,44 @@ "type": "function" } ], - "transactionHash": "0x159c9dfcc54590ec4e382a5b89e2c0609097a7a03713e04e1e82d8b209f6aa7a", + "transactionHash": "0x007d8de6018e9a681a6ed7bc2a4dd6a5edd713f70ab9da84cdcf83849cd8f7b5", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 8, - "gasUsed": "502877", - "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000002000000000000000000000000000000000000000000000000000800000000000000000040100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000040000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0xe8a6ca68f1e5e7fbf531e6bd605fc75e0a6e7ef1adeb68a02c248b8ff6673b8e", - "transactionHash": "0x159c9dfcc54590ec4e382a5b89e2c0609097a7a03713e04e1e82d8b209f6aa7a", + "transactionIndex": 19, + "gasUsed": "1841805", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000004000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000080000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100040000000000000000000000000000000000000000000000000000000000000000000100000", + "blockHash": "0xbaa3edba277c739ed20223b8b207a07a26ef2507ce1b5e7e2c8debd55392c99c", + "transactionHash": "0x007d8de6018e9a681a6ed7bc2a4dd6a5edd713f70ab9da84cdcf83849cd8f7b5", "logs": [ { - "transactionIndex": 8, - "blockNumber": 43756424, - "transactionHash": "0x159c9dfcc54590ec4e382a5b89e2c0609097a7a03713e04e1e82d8b209f6aa7a", + "transactionIndex": 19, + "blockNumber": 44419344, + "transactionHash": "0x007d8de6018e9a681a6ed7bc2a4dd6a5edd713f70ab9da84cdcf83849cd8f7b5", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", - "0x000000000000000000000000c275dc8be39f50d12f66b6a63629c39da5bae5bd" + "0x000000000000000000000000be188d6641e8b680743a4815dfa0f6208038960f" ], - "data": "0x0000000000000000000000000000000000000000000000000002ae0bc36d130000000000000000000000000000000000000000000000000000a997336b6daf800000000000000000000000000000000000000000000013b63190adb3f7be65c100000000000000000000000000000000000000000000000000a6e927a8009c800000000000000000000000000000000000000000000013b631935bbfbb2b78c1", - "logIndex": 52, - "blockHash": "0xe8a6ca68f1e5e7fbf531e6bd605fc75e0a6e7ef1adeb68a02c248b8ff6673b8e" + "data": "0x000000000000000000000000000000000000000000000000000e06eff4f9375d000000000000000000000000000000000000000000000000007cdad71d02d26a0000000000000000000000000000000000000000000035ca46fabd6e1d56c6bb000000000000000000000000000000000000000000000000006ed3e728099b0d0000000000000000000000000000000000000000000035ca4708c45e124ffe18", + "logIndex": 68, + "blockHash": "0xbaa3edba277c739ed20223b8b207a07a26ef2507ce1b5e7e2c8debd55392c99c" } ], - "blockNumber": 43756424, - "cumulativeGasUsed": "2432207", + "blockNumber": 44419344, + "cumulativeGasUsed": "5126038", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b935093509350935060007321D84679F9dd3f0e4914a806113CF329368d5253630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0x21D84679F9dd3f0e4914a806113CF329368d5253" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -244,7 +251,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -252,7 +259,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -260,7 +267,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/mumbai_production/P256SignerFactory.json b/deployments/mumbai_production/P256SignerFactory.json index ff0a39b..5f4f0cd 100644 --- a/deployments/mumbai_production/P256SignerFactory.json +++ b/deployments/mumbai_production/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x432870e7E5DBB4dF79f92aD0FA0FeF10f3b71219", + "address": "0x73dA77F0f2daaa88b908413495d3D0e37458212e", "abi": [ { "inputs": [ @@ -75,46 +75,46 @@ "type": "function" } ], - "transactionHash": "0x7c5ed20771317d19ba158251612cb06aa7974a80f2add21efb2c0b19500ddb1b", + "transactionHash": "0x8cec4e36c46de09c22bc40cd477e72df9926f5be4f83e5e09e20a65756f062de", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 1, "gasUsed": "195452", - "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000002000000000000000000000000000000000000000000000000000800000000000000000040100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000040000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0x7aaed9afeafc51f9f541de7e09d6784b444a8ca6dd18c109d1109d1ed4a9182b", - "transactionHash": "0x7c5ed20771317d19ba158251612cb06aa7974a80f2add21efb2c0b19500ddb1b", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000004000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000080000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100040000000000000000000000000000000000000000000000000000000000000000000100000", + "blockHash": "0x8eb3c0c2b2c4702a568f182e9da372dd468172357e710b627d8f21d04bd320a9", + "transactionHash": "0x8cec4e36c46de09c22bc40cd477e72df9926f5be4f83e5e09e20a65756f062de", "logs": [ { "transactionIndex": 1, - "blockNumber": 43756427, - "transactionHash": "0x7c5ed20771317d19ba158251612cb06aa7974a80f2add21efb2c0b19500ddb1b", + "blockNumber": 44419348, + "transactionHash": "0x8cec4e36c46de09c22bc40cd477e72df9926f5be4f83e5e09e20a65756f062de", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", - "0x000000000000000000000000c275dc8be39f50d12f66b6a63629c39da5bae5bd" + "0x000000000000000000000000be188d6641e8b680743a4815dfa0f6208038960f" ], - "data": "0x0000000000000000000000000000000000000000000000000001b384ad09e64000000000000000000000000000000000000000000000000000a6e927a785d6b00000000000000000000000000000000000000000000013b631dde0a66304bf4800000000000000000000000000000000000000000000000000a535a2fa7bf0700000000000000000000000000000000000000000000013b631df942b100ea588", - "logIndex": 5, - "blockHash": "0x7aaed9afeafc51f9f541de7e09d6784b444a8ca6dd18c109d1109d1ed4a9182b" + "data": "0x00000000000000000000000000000000000000000000000000021549a5178800000000000000000000000000000000000000000000000000006ed3e726640cca0000000000000000000000000000000000000000000035ca4768ad0a4e830bb3000000000000000000000000000000000000000000000000006cbe9d814c84ca0000000000000000000000000000000000000000000035ca476ac253f39a93b3", + "logIndex": 4, + "blockHash": "0x8eb3c0c2b2c4702a568f182e9da372dd468172357e710b627d8f21d04bd320a9" } ], - "blockNumber": 43756427, - "cumulativeGasUsed": "307522", + "blockNumber": 44419348, + "cumulativeGasUsed": "369254", "status": 1, "byzantium": true }, "args": [ - "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8" + "0x71558e9Ac314B17Eb665441aFF60914EAE391712" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/mumbai_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/mumbai_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/mumbai_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/mumbai_staging/P256Signer.json b/deployments/mumbai_staging/P256Signer.json index 5b5d97a..39d6339 100644 --- a/deployments/mumbai_staging/P256Signer.json +++ b/deployments/mumbai_staging/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x598caFAA35ccEa5Da78E96E66672711184bf0Ae3", + "address": "0xc1EB9d816Fd772afE2D7577c4B60C8D912d57f0E", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,44 @@ "type": "function" } ], - "transactionHash": "0xfeb101ae92198531a6ac29b939b3499cd4f7247210bb8bceda0fee3b65f4c6c8", + "transactionHash": "0x2a2a56d23cf1a6560a644739b68a7388bfe534f6baf435bc05d4e0698104c2ac", "receipt": { "to": "0x1C702034b2533639f25601024565b087f8cD9391", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 41, - "gasUsed": "502877", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x76ca9542278c21106c1274e3760ad42b0f6a993080fd7a84c86ae40cfcc4b41f", - "transactionHash": "0xfeb101ae92198531a6ac29b939b3499cd4f7247210bb8bceda0fee3b65f4c6c8", - "logs": [], - "blockNumber": 43757829, - "cumulativeGasUsed": "21718195", + "transactionIndex": 5, + "gasUsed": "1841805", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000002000000000000000000000000000000000000000000000000000800000000000000000040100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000040000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", + "blockHash": "0xb1aca10a03228643ba31a4c787423b429d75775b2899b0e585d9a129f4244f19", + "transactionHash": "0x2a2a56d23cf1a6560a644739b68a7388bfe534f6baf435bc05d4e0698104c2ac", + "logs": [ + { + "transactionIndex": 5, + "blockNumber": 44419937, + "transactionHash": "0x2a2a56d23cf1a6560a644739b68a7388bfe534f6baf435bc05d4e0698104c2ac", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", + "0x000000000000000000000000c275dc8be39f50d12f66b6a63629c39da5bae5bd" + ], + "data": "0x0000000000000000000000000000000000000000000000000013a155ee6be08d000000000000000000000000000000000000000000000000006cbe9d811fc8860000000000000000000000000000000000000000000013db1709cb71f4fad39d00000000000000000000000000000000000000000000000000591d4792b3e7f90000000000000000000000000000000000000000000013db171d6cc7e366b42a", + "logIndex": 11, + "blockHash": "0xb1aca10a03228643ba31a4c787423b429d75775b2899b0e585d9a129f4244f19" + } + ], + "blockNumber": 44419937, + "cumulativeGasUsed": "7622806", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073a8a027c9433A56b35e1efcC8F396C7cf8243f3c3630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xa8a027c9433A56b35e1efcC8F396C7cf8243f3c3" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +251,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +259,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +267,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/mumbai_staging/P256SignerFactory.json b/deployments/mumbai_staging/P256SignerFactory.json index 2f1c77f..cc3ba5e 100644 --- a/deployments/mumbai_staging/P256SignerFactory.json +++ b/deployments/mumbai_staging/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0xb673E2dceA6c3C6afCAF0F895eAD90A6a3811Bc9", + "address": "0x2C490ff08Bcc843be4894c4Ed51Af56D34A51bf4", "abi": [ { "inputs": [ @@ -75,46 +75,46 @@ "type": "function" } ], - "transactionHash": "0x7d2ae55e0f59a6a283bc9c225f414aea5e676fc71a0643a170c9b143cc124e3f", + "transactionHash": "0xd2c3bbdccdf589fcdd20e7b3b05d7c0399af8a4f3133970f97e272b5721f3db3", "receipt": { "to": "0x1C702034b2533639f25601024565b087f8cD9391", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 0, "gasUsed": "195452", - "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000100000000000010000000000000000000000008000000000000200000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000400000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0x0646f68a8b1f2d02c66fb985bb65d4e77678b32e59beb1195ae6f3d3aa0345ea", - "transactionHash": "0x7d2ae55e0f59a6a283bc9c225f414aea5e676fc71a0643a170c9b143cc124e3f", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000002000000000000000000000000000000000000000000000000000800000000000000000040100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000040000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", + "blockHash": "0xbf6af333aaf1b563e4023bd39c4982fefc2cf706cc2375699fdbaaad8a422b35", + "transactionHash": "0xd2c3bbdccdf589fcdd20e7b3b05d7c0399af8a4f3133970f97e272b5721f3db3", "logs": [ { "transactionIndex": 0, - "blockNumber": 43757833, - "transactionHash": "0x7d2ae55e0f59a6a283bc9c225f414aea5e676fc71a0643a170c9b143cc124e3f", + "blockNumber": 44419940, + "transactionHash": "0xd2c3bbdccdf589fcdd20e7b3b05d7c0399af8a4f3133970f97e272b5721f3db3", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", - "0x000000000000000000000000244c9aa5d417e0dc869ee5ab9b7430402368e2b2" + "0x000000000000000000000000c275dc8be39f50d12f66b6a63629c39da5bae5bd" ], - "data": "0x00000000000000000000000000000000000000000000000000029eb7a44fc2c80000000000000000000000000000000000000000000000000099347f772a384a0000000000000000000000000000000000000000000000110609d07bc450cd8d000000000000000000000000000000000000000000000000009695c7d2da7582000000000000000000000000000000000000000000000011060c6f3368a09055", + "data": "0x00000000000000000000000000000000000000000000000000030a9999a50b7800000000000000000000000000000000000000000000000000591d47910e59b60000000000000000000000000000000000000000000013db1752ca1dc01fca5f000000000000000000000000000000000000000000000000005612adf7694e3e0000000000000000000000000000000000000000000013db1755d4b759c4d5d7", "logIndex": 0, - "blockHash": "0x0646f68a8b1f2d02c66fb985bb65d4e77678b32e59beb1195ae6f3d3aa0345ea" + "blockHash": "0xbf6af333aaf1b563e4023bd39c4982fefc2cf706cc2375699fdbaaad8a422b35" } ], - "blockNumber": 43757833, + "blockNumber": 44419940, "cumulativeGasUsed": "195452", "status": 1, "byzantium": true }, "args": [ - "0x598caFAA35ccEa5Da78E96E66672711184bf0Ae3" + "0xc1EB9d816Fd772afE2D7577c4B60C8D912d57f0E" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/mumbai_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/mumbai_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/mumbai_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/muster_testnet/P256Signer.json b/deployments/muster_testnet/P256Signer.json index bd04d3b..6c07d0a 100644 --- a/deployments/muster_testnet/P256Signer.json +++ b/deployments/muster_testnet/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8", + "address": "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0xe1c54e2f3f83069d8315bb3454377cd3add32bebd6707572da6f40f30c76c950", + "transactionHash": "0xcbb8cc2bfb4c635f37d612526cfae9a789c97441e2fc1651323d1a8637ca591d", "receipt": { "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 1, - "gasUsed": "606731", + "gasUsed": "2218528", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xec702787a5226937931efbf56cfe514e6650f85f06d9a784e0a919466d7f98b0", - "transactionHash": "0xe1c54e2f3f83069d8315bb3454377cd3add32bebd6707572da6f40f30c76c950", + "blockHash": "0x601aa5f484a906567c18273b25417a812b5aa8986a50133c8c84dffa44b3dc28", + "transactionHash": "0xcbb8cc2bfb4c635f37d612526cfae9a789c97441e2fc1651323d1a8637ca591d", "logs": [], - "blockNumber": 9064, - "cumulativeGasUsed": "606731", + "blockNumber": 9747, + "cumulativeGasUsed": "2218528", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073B15bb4dE71bF6fbB91913872dB9F18E6C8897E9F630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xB15bb4dE71bF6fbB91913872dB9F18E6C8897E9F" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/muster_testnet/P256SignerFactory.json b/deployments/muster_testnet/P256SignerFactory.json index bd99251..1b86049 100644 --- a/deployments/muster_testnet/P256SignerFactory.json +++ b/deployments/muster_testnet/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x8072CB92Bd6EF882683cAaC8F28985F216ae9d6f", + "address": "0x841Da89727BB8c0807738230e3781D07b659653D", "abi": [ { "inputs": [ @@ -75,30 +75,30 @@ "type": "function" } ], - "transactionHash": "0xd42c33c486f9e513f8fede42c2370a188a6683a91aad548412dc941d292c38d3", + "transactionHash": "0xd5ec4a06795b9511fc50061276676deb125b6e4fdd03442af22625cb01a516d7", "receipt": { "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 1, - "gasUsed": "253418", + "gasUsed": "289796", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf9f27497ff5e0d83fcc3683a3bd75a7ee275817d0fb3da17add41c4e0da54a21", - "transactionHash": "0xd42c33c486f9e513f8fede42c2370a188a6683a91aad548412dc941d292c38d3", + "blockHash": "0x84576119128cdf827b9e8da1d596332ff40b94df6032307bc4a384765a10149c", + "transactionHash": "0xd5ec4a06795b9511fc50061276676deb125b6e4fdd03442af22625cb01a516d7", "logs": [], - "blockNumber": 9065, - "cumulativeGasUsed": "253418", + "blockNumber": 9748, + "cumulativeGasUsed": "289796", "status": 1, "byzantium": true }, "args": [ - "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8" + "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/muster_testnet/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/muster_testnet/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/muster_testnet/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/muster_testnet_production/P256Signer.json b/deployments/muster_testnet_production/P256Signer.json index d64ccea..3ed52eb 100644 --- a/deployments/muster_testnet_production/P256Signer.json +++ b/deployments/muster_testnet_production/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8", + "address": "0x71558e9Ac314B17Eb665441aFF60914EAE391712", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0xc9dfa3f0c5770754c86d5546cbbab827a263d2ffda0b86836253f0da9f7e222e", + "transactionHash": "0x9d19669f05ceba021dc32ff02b83129a86749120f4a4e1de4365c04acecc9faf", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 1, - "gasUsed": "614666", + "gasUsed": "2218984", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7e1d5ce9532ff0c8b99c801d39f3336daa4fc80f47dd65f5458980da7894cf79", - "transactionHash": "0xc9dfa3f0c5770754c86d5546cbbab827a263d2ffda0b86836253f0da9f7e222e", + "blockHash": "0xa34ba70612b68e596522161094f94b65b1d5817a30251e3a93e5ce0d6261618c", + "transactionHash": "0x9d19669f05ceba021dc32ff02b83129a86749120f4a4e1de4365c04acecc9faf", "logs": [], - "blockNumber": 9100, - "cumulativeGasUsed": "614666", + "blockNumber": 9749, + "cumulativeGasUsed": "2218984", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b935093509350935060007321D84679F9dd3f0e4914a806113CF329368d5253630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0x21D84679F9dd3f0e4914a806113CF329368d5253" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/muster_testnet_production/P256SignerFactory.json b/deployments/muster_testnet_production/P256SignerFactory.json index aea9698..910c3bd 100644 --- a/deployments/muster_testnet_production/P256SignerFactory.json +++ b/deployments/muster_testnet_production/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x432870e7E5DBB4dF79f92aD0FA0FeF10f3b71219", + "address": "0x73dA77F0f2daaa88b908413495d3D0e37458212e", "abi": [ { "inputs": [ @@ -75,30 +75,30 @@ "type": "function" } ], - "transactionHash": "0x2798efbc6fa2c865cb3965685b3a14c06f6903d80799e6b430f8051bbb3d1345", + "transactionHash": "0x4cc2963080f677604fbc2dfe563f2afe704f844e926f84de65e86667b6465b04", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 1, - "gasUsed": "258101", + "gasUsed": "289339", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x9534a848418e1f2279a7070273d7906288fca67fa25c599ef92fa4a5f888ceaa", - "transactionHash": "0x2798efbc6fa2c865cb3965685b3a14c06f6903d80799e6b430f8051bbb3d1345", + "blockHash": "0xdb8fea40324e025e39444348efaccf318bc5bb5c4b273b60b01341df4d5bd848", + "transactionHash": "0x4cc2963080f677604fbc2dfe563f2afe704f844e926f84de65e86667b6465b04", "logs": [], - "blockNumber": 9101, - "cumulativeGasUsed": "258101", + "blockNumber": 9750, + "cumulativeGasUsed": "289339", "status": 1, "byzantium": true }, "args": [ - "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8" + "0x71558e9Ac314B17Eb665441aFF60914EAE391712" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/muster_testnet_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/muster_testnet_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/muster_testnet_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/muster_testnet_staging/P256Signer.json b/deployments/muster_testnet_staging/P256Signer.json index 026bcc7..cca2a3b 100644 --- a/deployments/muster_testnet_staging/P256Signer.json +++ b/deployments/muster_testnet_staging/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x598caFAA35ccEa5Da78E96E66672711184bf0Ae3", + "address": "0xc1EB9d816Fd772afE2D7577c4B60C8D912d57f0E", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0x34e2858a72d8230cc36dfbffaed1a7299be1d99301d2dce7cfac5ddb8afc8191", + "transactionHash": "0xa302e2be3b1d55a4b3ab05cfd224b4036c2e4c1ddb87879822f099a9491bf0a3", "receipt": { "to": "0x1C702034b2533639f25601024565b087f8cD9391", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 1, - "gasUsed": "616182", + "gasUsed": "2217310", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2734b6ef7d3db69d4377b6bd39b7081cc58fee56201dee5c27de0da66f83b0ae", - "transactionHash": "0x34e2858a72d8230cc36dfbffaed1a7299be1d99301d2dce7cfac5ddb8afc8191", + "blockHash": "0xdd334c25f903d8256dfa2f3a3b2bfe963bb52b485e753228fd0d22df2878622b", + "transactionHash": "0xa302e2be3b1d55a4b3ab05cfd224b4036c2e4c1ddb87879822f099a9491bf0a3", "logs": [], - "blockNumber": 9123, - "cumulativeGasUsed": "616182", + "blockNumber": 9752, + "cumulativeGasUsed": "2217310", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073a8a027c9433A56b35e1efcC8F396C7cf8243f3c3630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xa8a027c9433A56b35e1efcC8F396C7cf8243f3c3" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/muster_testnet_staging/P256SignerFactory.json b/deployments/muster_testnet_staging/P256SignerFactory.json index f6b9d23..7d31aea 100644 --- a/deployments/muster_testnet_staging/P256SignerFactory.json +++ b/deployments/muster_testnet_staging/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0xb673E2dceA6c3C6afCAF0F895eAD90A6a3811Bc9", + "address": "0x2C490ff08Bcc843be4894c4Ed51Af56D34A51bf4", "abi": [ { "inputs": [ @@ -75,30 +75,30 @@ "type": "function" } ], - "transactionHash": "0xe007690050839404be6cb6bd47b07622244465bf76ccd7972ee8c096c3dde0ba", + "transactionHash": "0xc86c418f2daee3d8bfd78151e05906121427f22051ede8a31917492695f59883", "receipt": { "to": "0x1C702034b2533639f25601024565b087f8cD9391", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 1, - "gasUsed": "259201", + "gasUsed": "288327", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc47157d99cdbe2ae3f7469317c93de266583750cadc25df39992d4bf2c334bd3", - "transactionHash": "0xe007690050839404be6cb6bd47b07622244465bf76ccd7972ee8c096c3dde0ba", + "blockHash": "0xb76ac33c9b7099db97cd07cd35c77c3eea31c42dd2ee2ea7c71bc5f3a947241e", + "transactionHash": "0xc86c418f2daee3d8bfd78151e05906121427f22051ede8a31917492695f59883", "logs": [], - "blockNumber": 9124, - "cumulativeGasUsed": "259201", + "blockNumber": 9753, + "cumulativeGasUsed": "288327", "status": 1, "byzantium": true }, "args": [ - "0x598caFAA35ccEa5Da78E96E66672711184bf0Ae3" + "0xc1EB9d816Fd772afE2D7577c4B60C8D912d57f0E" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/muster_testnet_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/muster_testnet_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/muster_testnet_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/polygon/P256Signer.json b/deployments/polygon/P256Signer.json index b592821..0fdb077 100644 --- a/deployments/polygon/P256Signer.json +++ b/deployments/polygon/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8", + "address": "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,15 +137,44 @@ "type": "function" } ], - "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xB15bb4dE71bF6fbB91913872dB9F18E6C8897E9F" + "transactionHash": "0x3617303198a493d13b8c781cb8871ca22493d24e63afb087edbb2a0d024131dc", + "receipt": { + "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", + "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "contractAddress": null, + "transactionIndex": 7, + "gasUsed": "1841805", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000011000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100020000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000020100000", + "blockHash": "0xc21db5b4c21137a17ed8cd835cf4e84424fffc97c0920273107c121c6e601759", + "transactionHash": "0x3617303198a493d13b8c781cb8871ca22493d24e63afb087edbb2a0d024131dc", + "logs": [ + { + "transactionIndex": 7, + "blockNumber": 51962837, + "transactionHash": "0x3617303198a493d13b8c781cb8871ca22493d24e63afb087edbb2a0d024131dc", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", + "0x000000000000000000000000794e44d1334a56fea7f4df12633b88820d0c5888" + ], + "data": "0x000000000000000000000000000000000000000000000000040e0c501463c61700000000000000000000000000000000000000000000000043513e67807aab480000000000000000000000000000000000000000000002226419329891c0a5880000000000000000000000000000000000000000000000003f4332176c16e53100000000000000000000000000000000000000000000022268273ee8a6246b9f", + "logIndex": 27, + "blockHash": "0xc21db5b4c21137a17ed8cd835cf4e84424fffc97c0920273107c121c6e601759" + } + ], + "blockNumber": 51962837, + "cumulativeGasUsed": "2649932", + "status": 1, + "byzantium": true }, + "args": [], + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -212,7 +251,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -220,7 +259,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -228,7 +267,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/polygon/P256SignerFactory.json b/deployments/polygon/P256SignerFactory.json index 0e6141c..bb75d72 100644 --- a/deployments/polygon/P256SignerFactory.json +++ b/deployments/polygon/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x8072CB92Bd6EF882683cAaC8F28985F216ae9d6f", + "address": "0x841Da89727BB8c0807738230e3781D07b659653D", "abi": [ { "inputs": [ @@ -75,14 +75,46 @@ "type": "function" } ], + "transactionHash": "0xd5d09fd293470c4b3e0400323ce9ba0fa0b5e31c557a07af22f1f5ab3eb6b3ca", + "receipt": { + "to": "0x6A78a27E52fa669C0a5246574Ece2e9a64c483B1", + "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", + "contractAddress": null, + "transactionIndex": 23, + "gasUsed": "195452", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000201000000000000000000000020000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000020000000000000100000", + "blockHash": "0xbd6222811bf912975527be42eb862aead16f16dc67c511db362a92bec319f3b8", + "transactionHash": "0xd5d09fd293470c4b3e0400323ce9ba0fa0b5e31c557a07af22f1f5ab3eb6b3ca", + "logs": [ + { + "transactionIndex": 23, + "blockNumber": 51962840, + "transactionHash": "0xd5d09fd293470c4b3e0400323ce9ba0fa0b5e31c557a07af22f1f5ab3eb6b3ca", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", + "0x000000000000000000000000742d13f0b2a19c823bdd362b16305e4704b97a38" + ], + "data": "0x000000000000000000000000000000000000000000000000006f97b727f01fcc0000000000000000000000000000000000000000000000003e349006c65f1b48000000000000000000000000000000000000000000001d561cb9889898bacf3c0000000000000000000000000000000000000000000000003dc4f84f9e6efb7c000000000000000000000000000000000000000000001d561d29204fc0aaef08", + "logIndex": 100, + "blockHash": "0xbd6222811bf912975527be42eb862aead16f16dc67c511db362a92bec319f3b8" + } + ], + "blockNumber": 51962840, + "cumulativeGasUsed": "4359068", + "status": 1, + "byzantium": true + }, "args": [ - "0x10eCfe0ee8e7f192067d409Bb964735C900d3dF8" + "0x52E7e05A9F333c17A5b86e92799e9b7aD13d3503" ], - "numDeployments": 4, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 5, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/polygon/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/polygon/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/polygon/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/polygon_production/P256Signer.json b/deployments/polygon_production/P256Signer.json index abc5018..8c37f0d 100644 --- a/deployments/polygon_production/P256Signer.json +++ b/deployments/polygon_production/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8", + "address": "0x71558e9Ac314B17Eb665441aFF60914EAE391712", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,47 +137,44 @@ "type": "function" } ], - "transactionHash": "0xb474a54fd22b1bc0674499187a727d717352280fb17a122515d1214f1d8f31e3", + "transactionHash": "0xd97938a52a0466b198ce7c4386c37d91755ebb2b50537910a5f55b90551f4804", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 48, - "gasUsed": "502877", - "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000090000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100010000000000000000000000000000000000080000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0x65606a3a80d5ba05a447c60d29e713e0c593f87ae657647ac11d7a87ee343829", - "transactionHash": "0xb474a54fd22b1bc0674499187a727d717352280fb17a122515d1214f1d8f31e3", + "transactionIndex": 2, + "gasUsed": "1841805", + "logsBloom": "0x00000000000001000000000000000000000000000000000001000000000000000000000000010000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000004000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000040000000000000000000000000000000000000000000000100000", + "blockHash": "0x22216a16bce24d226f9575c41c45e3e6c3d25d72b48485e3dbd57a54a8ce5bd5", + "transactionHash": "0xd97938a52a0466b198ce7c4386c37d91755ebb2b50537910a5f55b90551f4804", "logs": [ { - "transactionIndex": 48, - "blockNumber": 51306955, - "transactionHash": "0xb474a54fd22b1bc0674499187a727d717352280fb17a122515d1214f1d8f31e3", + "transactionIndex": 2, + "blockNumber": 51963434, + "transactionHash": "0xd97938a52a0466b198ce7c4386c37d91755ebb2b50537910a5f55b90551f4804", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", - "0x00000000000000000000000060e274b09f701107a4b3226fcc1376ebda3cdd92" + "0x000000000000000000000000bdbd4347b082d9d6bdf2da4555a37ce52a2e2120" ], - "data": "0x000000000000000000000000000000000000000000000000003ceae157d5e35d00000000000000000000000000000000000000000000000053788b833357a03100000000000000000000000000000000000000000000044fc4c94a7e905fdf0d000000000000000000000000000000000000000000000000533ba0a1db81bcd400000000000000000000000000000000000000000000044fc506355fe835c26a", - "logIndex": 213, - "blockHash": "0x65606a3a80d5ba05a447c60d29e713e0c593f87ae657647ac11d7a87ee343829" + "data": "0x00000000000000000000000000000000000000000000000003c7a0778888dd2e0000000000000000000000000000000000000000000000003da9af83c83e5b480000000000000000000000000000000000000000000052f7690158ea2d70bde900000000000000000000000000000000000000000000000039e20f0c3fb57e1a0000000000000000000000000000000000000000000052f76cc8f961b5f99b17", + "logIndex": 10, + "blockHash": "0x22216a16bce24d226f9575c41c45e3e6c3d25d72b48485e3dbd57a54a8ce5bd5" } ], - "blockNumber": 51306955, - "cumulativeGasUsed": "6336658", + "blockNumber": 51963434, + "cumulativeGasUsed": "2065825", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b935093509350935060007321D84679F9dd3f0e4914a806113CF329368d5253630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0x21D84679F9dd3f0e4914a806113CF329368d5253" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -244,7 +251,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -252,7 +259,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -260,7 +267,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/polygon_production/P256SignerFactory.json b/deployments/polygon_production/P256SignerFactory.json index d4b8275..ffcba64 100644 --- a/deployments/polygon_production/P256SignerFactory.json +++ b/deployments/polygon_production/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x432870e7E5DBB4dF79f92aD0FA0FeF10f3b71219", + "address": "0x73dA77F0f2daaa88b908413495d3D0e37458212e", "abi": [ { "inputs": [ @@ -75,46 +75,46 @@ "type": "function" } ], - "transactionHash": "0x06f7cf93a1d5582fe765d03b0fc91f9c9448530beece00a490dd1a92cd4cc58f", + "transactionHash": "0x31a42bd582441c4842edad7a874e722121bc1451dfe10e5d88ce42b1c5d2414f", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 45, + "transactionIndex": 3, "gasUsed": "195452", - "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000090000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100010000000000000000000000000000000000080000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0xaa6e6a6880f3c08a5b7cdf57cf273706069c81332eb3810d8fb5e610a29dfd52", - "transactionHash": "0x06f7cf93a1d5582fe765d03b0fc91f9c9448530beece00a490dd1a92cd4cc58f", + "logsBloom": "0x00000000000001000000000000000000000000000000000001000000000000000000000000010000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000004000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000040000000000000000000000000000000000000000000000100000", + "blockHash": "0x56631d8e0d1cadf2d246bcb62d10506a6b7f9d2732253fe1856b3b56be8289f2", + "transactionHash": "0x31a42bd582441c4842edad7a874e722121bc1451dfe10e5d88ce42b1c5d2414f", "logs": [ { - "transactionIndex": 45, - "blockNumber": 51306958, - "transactionHash": "0x06f7cf93a1d5582fe765d03b0fc91f9c9448530beece00a490dd1a92cd4cc58f", + "transactionIndex": 3, + "blockNumber": 51963437, + "transactionHash": "0x31a42bd582441c4842edad7a874e722121bc1451dfe10e5d88ce42b1c5d2414f", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", - "0x00000000000000000000000060e274b09f701107a4b3226fcc1376ebda3cdd92" + "0x000000000000000000000000bdbd4347b082d9d6bdf2da4555a37ce52a2e2120" ], - "data": "0x0000000000000000000000000000000000000000000000000019ed713dbe015c00000000000000000000000000000000000000000000000052c5e31da445583100000000000000000000000000000000000000000000044fde32d33a1d44979700000000000000000000000000000000000000000000000052abf5ac668756d500000000000000000000000000000000000000000000044fde4cc0ab5b0298f3", - "logIndex": 174, - "blockHash": "0xaa6e6a6880f3c08a5b7cdf57cf273706069c81332eb3810d8fb5e610a29dfd52" + "data": "0x00000000000000000000000000000000000000000000000000669eccbe96858c000000000000000000000000000000000000000000000000388d01230e22cb480000000000000000000000000000000000000000000052f78ac67c547091e1cd000000000000000000000000000000000000000000000000382662564f8c45bc0000000000000000000000000000000000000000000052f78b2d1b212f286759", + "logIndex": 13, + "blockHash": "0x56631d8e0d1cadf2d246bcb62d10506a6b7f9d2732253fe1856b3b56be8289f2" } ], - "blockNumber": 51306958, - "cumulativeGasUsed": "6149596", + "blockNumber": 51963437, + "cumulativeGasUsed": "722800", "status": 1, "byzantium": true }, "args": [ - "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8" + "0x71558e9Ac314B17Eb665441aFF60914EAE391712" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/polygon_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/polygon_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/polygon_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/polygon_staging/P256Signer.json b/deployments/polygon_staging/P256Signer.json index 781eb68..abac5d8 100644 --- a/deployments/polygon_staging/P256Signer.json +++ b/deployments/polygon_staging/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x598caFAA35ccEa5Da78E96E66672711184bf0Ae3", + "address": "0xc1EB9d816Fd772afE2D7577c4B60C8D912d57f0E", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,47 +137,44 @@ "type": "function" } ], - "transactionHash": "0x61e598cba9881e742f71689d97c557e2157f1d2167bd276dc82e5a55207991c7", + "transactionHash": "0x5028462a9804cde6791cd7952db5703eee1a2c77715009491a0fe3dde9c70a87", "receipt": { "to": "0x1C702034b2533639f25601024565b087f8cD9391", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 64, - "gasUsed": "502877", - "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000000000000000000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000800000000008000001000000008000000000000000000000100000000000000000020000000000000000000000000000000000000000000000000000100000", - "blockHash": "0xbb124c77b31fc557941195afa93c5b7e2c198f16798a4dd758b15d1d8c2ee01a", - "transactionHash": "0x61e598cba9881e742f71689d97c557e2157f1d2167bd276dc82e5a55207991c7", + "transactionIndex": 1, + "gasUsed": "1841805", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000018000000000000000000000008000000000000000000000000000000080000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000080000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", + "blockHash": "0x5463361433ee69b32d3fa0d74e6fe863963c9ba7eeb7870ceb14395037cd08fe", + "transactionHash": "0x5028462a9804cde6791cd7952db5703eee1a2c77715009491a0fe3dde9c70a87", "logs": [ { - "transactionIndex": 64, - "blockNumber": 51311679, - "transactionHash": "0x61e598cba9881e742f71689d97c557e2157f1d2167bd276dc82e5a55207991c7", + "transactionIndex": 1, + "blockNumber": 51963984, + "transactionHash": "0x5028462a9804cde6791cd7952db5703eee1a2c77715009491a0fe3dde9c70a87", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", - "0x00000000000000000000000067b94473d81d0cd00849d563c94d0432ac988b49" + "0x000000000000000000000000f0245f6251bef9447a08766b9da2b07b28ad80b0" ], - "data": "0x0000000000000000000000000000000000000000000000000041b72898e9423c0000000000000000000000000000000000000000000000004e5ec9bd60596831000000000000000000000000000000000000000000001b410e443ee5bdb865170000000000000000000000000000000000000000000000004e1d1294c77025f5000000000000000000000000000000000000000000001b410e85f60e56a1a753", - "logIndex": 235, - "blockHash": "0xbb124c77b31fc557941195afa93c5b7e2c198f16798a4dd758b15d1d8c2ee01a" + "data": "0x000000000000000000000000000000000000000000000000038e5f4f0619cfb2000000000000000000000000000000000000000000000000380220a010020b4800000000000000000000000000000000000000000000067cfaf88d01eb9da5130000000000000000000000000000000000000000000000003473c15109e83b9600000000000000000000000000000000000000000000067cfe86ec50f1b774c5", + "logIndex": 2, + "blockHash": "0x5463361433ee69b32d3fa0d74e6fe863963c9ba7eeb7870ceb14395037cd08fe" } ], - "blockNumber": 51311679, - "cumulativeGasUsed": "6939342", + "blockNumber": 51963984, + "cumulativeGasUsed": "1961165", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073a8a027c9433A56b35e1efcC8F396C7cf8243f3c3630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0xa8a027c9433A56b35e1efcC8F396C7cf8243f3c3" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -244,7 +251,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -252,7 +259,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -260,7 +267,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/polygon_staging/P256SignerFactory.json b/deployments/polygon_staging/P256SignerFactory.json index d5e9c6a..0d743f3 100644 --- a/deployments/polygon_staging/P256SignerFactory.json +++ b/deployments/polygon_staging/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0xb673E2dceA6c3C6afCAF0F895eAD90A6a3811Bc9", + "address": "0x2C490ff08Bcc843be4894c4Ed51Af56D34A51bf4", "abi": [ { "inputs": [ @@ -75,46 +75,46 @@ "type": "function" } ], - "transactionHash": "0x4a2ee38df407d09135adc10cf06e9fa5f6824bd592de294a228552a8bdfe7586", + "transactionHash": "0xd5e926e9b70844291ff7e4444ed9568a7fa5851d9943c688e700e1d5c4a745c4", "receipt": { "to": "0x1C702034b2533639f25601024565b087f8cD9391", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, - "transactionIndex": 136, + "transactionIndex": 0, "gasUsed": "195452", - "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000008800000000000000000000000000000000000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000020000000000000000000000000000000000000002000000000000000000000000100000", - "blockHash": "0x22a12bdb00f84e228b83f0b204a4af0c051890032a4f4204e41d83f75e1a508e", - "transactionHash": "0x4a2ee38df407d09135adc10cf06e9fa5f6824bd592de294a228552a8bdfe7586", + "logsBloom": "0x00000000000001000000000000000000000000000000000000000000000000000000000000018000000000000000000000008000000000000000000000000000000080000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000080000200000000000000000000000000000000000000000000000000000000000004000000000000008000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", + "blockHash": "0x76647233c85be942367a7a74d648a3c676c6ffcb9a99c46aeae3acbb0adeecaf", + "transactionHash": "0xd5e926e9b70844291ff7e4444ed9568a7fa5851d9943c688e700e1d5c4a745c4", "logs": [ { - "transactionIndex": 136, - "blockNumber": 51311681, - "transactionHash": "0x4a2ee38df407d09135adc10cf06e9fa5f6824bd592de294a228552a8bdfe7586", + "transactionIndex": 0, + "blockNumber": 51963988, + "transactionHash": "0xd5e926e9b70844291ff7e4444ed9568a7fa5851d9943c688e700e1d5c4a745c4", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x00000000000000000000000065245f19c92ac5adce53244406ad126398ef203a", - "0x000000000000000000000000959c65b72147faf3450d8b50a0de57e72ffc5e0d" + "0x000000000000000000000000f0245f6251bef9447a08766b9da2b07b28ad80b0" ], - "data": "0x000000000000000000000000000000000000000000000000001c45fb29bf55ac0000000000000000000000000000000000000000000000004cf978f24234d8310000000000000000000000000000000000000000000006d05c175b9842dad8a20000000000000000000000000000000000000000000000004cdd32f7187582850000000000000000000000000000000000000000000006d05c33a1936c9a2e4e", - "logIndex": 515, - "blockHash": "0x22a12bdb00f84e228b83f0b204a4af0c051890032a4f4204e41d83f75e1a508e" + "data": "0x0000000000000000000000000000000000000000000000000060e149b6e19c2400000000000000000000000000000000000000000000000032e5723f55e67b4800000000000000000000000000000000000000000000067d2165600eb394710e000000000000000000000000000000000000000000000000328490f59f04df2400000000000000000000000000000000000000000000067d21c641586a760d32", + "logIndex": 0, + "blockHash": "0x76647233c85be942367a7a74d648a3c676c6ffcb9a99c46aeae3acbb0adeecaf" } ], - "blockNumber": 51311681, - "cumulativeGasUsed": "15492437", + "blockNumber": 51963988, + "cumulativeGasUsed": "195452", "status": 1, "byzantium": true }, "args": [ - "0x598caFAA35ccEa5Da78E96E66672711184bf0Ae3" + "0xc1EB9d816Fd772afE2D7577c4B60C8D912d57f0E" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/polygon_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/polygon_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/polygon_staging/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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/redstone_holesky_production/P256Signer.json b/deployments/redstone_holesky_production/P256Signer.json index 42b4684..a522e20 100644 --- a/deployments/redstone_holesky_production/P256Signer.json +++ b/deployments/redstone_holesky_production/P256Signer.json @@ -1,5 +1,5 @@ { - "address": "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8", + "address": "0x71558e9Ac314B17Eb665441aFF60914EAE391712", "abi": [ { "inputs": [], @@ -11,6 +11,16 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "InvalidAuthenticatorData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidClientData", + "type": "error" + }, { "inputs": [], "name": "InvalidHash", @@ -127,31 +137,28 @@ "type": "function" } ], - "transactionHash": "0xa150c1e4fc054c540adfb70288e8dcde8f8a355be10e126b462ead512e158e93", + "transactionHash": "0x2e20b027bbaeed9b9d232adff0a22de7971c0e4fc2b7fb15d68332c3b146d6c8", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", "contractAddress": null, "transactionIndex": 1, - "gasUsed": "502749", + "gasUsed": "1841285", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3f90c8854f389ed8150bc1cb87bdb86ec5cfa84da3c3011354ce53d0bd03919d", - "transactionHash": "0xa150c1e4fc054c540adfb70288e8dcde8f8a355be10e126b462ead512e158e93", + "blockHash": "0xb21d17245b0abf62dde293bd9e71d6ef2b3e733858a03e111bb1e26e0cd9fadf", + "transactionHash": "0x2e20b027bbaeed9b9d232adff0a22de7971c0e4fc2b7fb15d68332c3b146d6c8", "logs": [], - "blockNumber": 1848289, - "cumulativeGasUsed": "549614", + "blockNumber": 2578748, + "cumulativeGasUsed": "1888186", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "metadata": "{\"compiler\":{\"version\":\"0.8.20+commit.a1b79de6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyInitialized\",\"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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506000805460ff191660011790556107c18061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b935093509350935060007321D84679F9dd3f0e4914a806113CF329368d5253630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004610475565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c36101023660046104bc565b61017a565b61008060025481565b61012361011e366004610516565b6101ae565b005b60006101528360405160200161013d91815260200190565b60405160208183030381529060405283610222565b507f1626ba7e0000000000000000000000000000000000000000000000000000000092915050565b60006101868383610222565b507f20c13b0b0000000000000000000000000000000000000000000000000000000092915050565b60005460ff16156101eb576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b6000828051906020012090506000806000808580602001905181019061024891906105a9565b9350935093509350600073__$d89787f8caa2dcaf364e9349db6aeaba37$__630d5efec9866001878a8888604051806040016040528060015481526020016002548152506040518863ffffffff1660e01b81526004016102ae97969594939291906106da565b602060405180830381865af41580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610762565b905080610328576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561038457610384610332565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156103d1576103d1610332565b604052919050565b600067ffffffffffffffff8211156103f3576103f3610332565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261043057600080fd5b813561044361043e826103d9565b61038a565b81815284602083860101111561045857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561048857600080fd5b82359150602083013567ffffffffffffffff8111156104a657600080fd5b6104b28582860161041f565b9150509250929050565b600080604083850312156104cf57600080fd5b823567ffffffffffffffff808211156104e757600080fd5b6104f38683870161041f565b9350602085013591508082111561050957600080fd5b506104b28582860161041f565b6000806040838503121561052957600080fd5b50508035926020909101359150565b60005b8381101561055357818101518382015260200161053b565b50506000910152565b600082601f83011261056d57600080fd5b815161057b61043e826103d9565b81815284602083860101111561059057600080fd5b6105a1826020830160208701610538565b949350505050565b60008060008060a085870312156105bf57600080fd5b845167ffffffffffffffff808211156105d757600080fd5b6105e38883890161055c565b95506020915081870151818111156105fa57600080fd5b61060689828a0161055c565b955050506040860151925086607f87011261062057600080fd5b610628610361565b8060a088018981111561063a57600080fd5b606089015b81811015610656578051845292840192840161063f565b505080935050505092959194509250565b6000815180845261067f816020860160208601610538565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8060005b60028110156106d45781518452602093840193909101906001016106b5565b50505050565b60006101208083526106ee8184018b610667565b90507fff000000000000000000000000000000000000000000000000000000000000008960f81b166020840152828103604084015261072d8189610667565b91505085606083015284608083015261074960a08301856106b1565b61075660e08301846106b1565b98975050505050505050565b60006020828403121561077457600080fd5b8151801515811461078457600080fd5b939250505056fea26469706673582212207cd1278d2c8b4857225fb653cc9b5ae2215dc6321928bc580a16e6fac9c293ec64736f6c63430008140033", - "libraries": { - "WrapperFCLWebAuthn": "0x21D84679F9dd3f0e4914a806113CF329368d5253" - }, + "numDeployments": 2, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x608060405234801561001057600080fd5b506000805460ff1916600117905561204b8061002d6000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806320c13b0b1161005057806320c13b0b146100f4578063a56dfe4a14610107578063e4a301161461011057600080fd5b80630c55699c14610077578063158ef93e146100935780631626ba7e146100b0575b600080fd5b61008060015481565b6040519081526020015b60405180910390f35b6000546100a09060ff1681565b604051901515815260200161008a565b6100c36100be366004611cb9565b610125565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161008a565b6100c3610102366004611d34565b61017c565b61008060025481565b61012361011e366004611e20565b6101b2565b005b60006101538460405160200161013d91815260200190565b6040516020818303038152906040528484610226565b507f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6000610189848484610226565b507f20c13b0b000000000000000000000000000000000000000000000000000000009392505050565b60005460ff16156101ef576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591909155600255565b8251602084012082600061028061023d8380611e42565b7f010000000000000000000000000000000000000000000000000000000000000061026b6020870187611e42565b888860400135896060016001546002546102c1565b9050806102b9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000806102d48c8c8c8c8c8c8c8c6102f5565b905060006102e482878787610598565b9d9c50505050505050505050505050565b60007fff000000000000000000000000000000000000000000000000000000000000008716878a8a602081811061032e5761032e611ea7565b9050013560f81c60f81b167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614610392576040517ffc93479200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103be856040516020016103aa91815260200190565b6040516020818303038152906040526106f7565b90506000815167ffffffffffffffff8111156103dc576103dc611d05565b6040519080825280601f01601f191660200182016040528015610406576020820181803683370190505b50905080518589016020830137600081516020830120905080836040516020016104309190611ed6565b604051602081830303815290604052805190602001201461047d576040517febab5d2900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506000915061048f9050896020611f34565b67ffffffffffffffff8111156104a7576104a7611d05565b6040519080825280601f01601f1916602001820160405280156104d1576020820181803683370190505b509050888a60208301376000600288886040516104ef929190611f47565b602060405180830381855afa15801561050c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061052f9190611f57565b90508060208b018301526002826040516105499190611ed6565b602060405180830381855afa158015610566573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906105899190611f57565b9b9a5050505050505050505050565b6000833560208501358115806105ce57507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518210155b806105d7575080155b8061060257507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518110155b15610612576000925050506106ef565b61061c8585610866565b61062b576000925050506106ef565b6000610636826109e0565b905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551828a09905060007fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325518386099050600061069689898585610a64565b90507fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325516106e3877fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551611f70565b82081596505050505050505b949350505050565b6060815160000361071657505060408051602081019091526000815290565b6000604051806060016040528060408152602001611fd660409139905060006003845160026107459190611f34565b61074f9190611f83565b61075a906004611fbe565b67ffffffffffffffff81111561077257610772611d05565b6040519080825280601f01601f19166020018201604052801561079c576020820181803683370190505b509050600182016020820185865187015b80821015610808576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506107ad565b5050600386510660018114610824576002811461082f57610836565b600282039150610836565b6001820391505b508290037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018252509392505050565b600082158015610874575081155b8061089e57507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83145b806108c857507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82145b156108d5575060006109da565b60007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409905060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000fffffffffffffffffffffffc87097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09090890507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff7f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8208919091149150505b92915050565b600060405160208152602080820152602060408201528260608201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255160a082015260208160c0836005600019fa610a5d57600080fd5b5192915050565b600080808060ff818088158015610a79575087155b15610a8d57600096505050505050506106ef565b610ad97f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2967f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f58d8d611561565b909250905081158015610aea575080155b15610b3c577fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551887fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551038a089850600097505b600189841c16600189851c1660011b015b80610b6f5760018403935060018a851c1660018a861c1660011b019050610b4d565b50600189841c16600189851c1660011b01955060018603610bd1577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29696507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f593505b60028603610be0578a96508993505b60038603610bef578196508093505b60018303925060019550600194505b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11156114b1577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff846002097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8182097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818a097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82840992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8d087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e08096003097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff89850998507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a840999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838409089a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08820992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff837fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a870908975060018d881c1660018d891c1660011b01905080610eda57877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff039750505050506114a6565b60018103610f29577f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29693507f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f592505b60028103610f38578e93508d92505b60038103610f47578593508492505b89610f6057509198506001975087965094506114a69050565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b8609087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d88090893508061129f578361129f577fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd0994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85860993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848d0992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84860994507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808c7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038e087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8d8f080990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8160030991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a860999507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8b85099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80847fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848509089b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808d7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038508830993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808a87098508985050505050506114a6565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8483097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838d099b507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818c099a507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff838e097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff847fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff878809080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80838d097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff03860809089a50505050809a50505050505b600183039250610bfe565b60405186606082015260208152602080820152602060408201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa61152c57600080fd5b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff815189099c9b505050505050505050505050565b6000808080866115785785859350935050506115e6565b8461158a5787879350935050506115e6565b858814801561159857508487145b156115b9576115aa88886001806115ef565b929a50909850925090506115d3565b6115c888886001808a8a611879565b929a50909850925090505b6115df88888484611b3e565b9350935050505b94509492505050565b6000806000807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8760020993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84850991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82890990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86830991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff807fffffffff00000001000000000000000000000000ffffffffffffffffffffffff888b087fffffffff00000001000000000000000000000000ffffffffffffffffffffffff897fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038c080960030995507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80827fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8889090893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038308870997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff85840990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff808885097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff0389089250945094509450949050565b6000806000808860000361189857508492508391506001905080611b31565b7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff9889039889818988090894507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a7fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8a89090895507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86870993507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff86850992507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff84890991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff83880990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff848b0997507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80897fffffffff00000001000000000000000000000000fffffffffffffffffffffffd097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff857fffffffff00000001000000000000000000000000ffffffffffffffffffffffff037fffffffff00000001000000000000000000000000ffffffffffffffffffffffff898a09080893507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff80848b097fffffffff00000001000000000000000000000000ffffffffffffffffffffffff877fffffffff00000001000000000000000000000000ffffffffffffffffffffffff887fffffffff00000001000000000000000000000000ffffffffffffffffffffffff038d08090892505b9650965096509692505050565b6000806000611b4c84611bf3565b90507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff818709915060007fffffffff00000001000000000000000000000000ffffffffffffffffffffffff82870990507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff81820991507fffffffff00000001000000000000000000000000ffffffffffffffffffffffff8289099350505094509492505050565b600060405160208152602080820152602060408201528260608201527fffffffff00000001000000000000000000000000fffffffffffffffffffffffd60808201527fffffffff00000001000000000000000000000000ffffffffffffffffffffffff60a082015260208160c0836005600019fa610a5d57600080fd5b60008083601f840112611c8257600080fd5b50813567ffffffffffffffff811115611c9a57600080fd5b602083019150836020828501011115611cb257600080fd5b9250929050565b600080600060408486031215611cce57600080fd5b83359250602084013567ffffffffffffffff811115611cec57600080fd5b611cf886828701611c70565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060408486031215611d4957600080fd5b833567ffffffffffffffff80821115611d6157600080fd5b818601915086601f830112611d7557600080fd5b813581811115611d8757611d87611d05565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611dcd57611dcd611d05565b81604052828152896020848701011115611de657600080fd5b826020860160208301376000602084830101528097505050506020860135915080821115611e1357600080fd5b50611cf886828701611c70565b60008060408385031215611e3357600080fd5b50508035926020909101359150565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e7757600080fd5b83018035915067ffffffffffffffff821115611e9257600080fd5b602001915036819003821315611cb257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000825160005b81811015611ef75760208186018101518583015201611edd565b506000920191825250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109da576109da611f05565b8183823760009101908152919050565b600060208284031215611f6957600080fd5b5051919050565b818103818111156109da576109da611f05565b600082611fb9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176109da576109da611f0556fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5fa264697066735822122010b19bcb302b393f0f07ede9ec3810838497a4931544263dc93726e735cb3b0e64736f6c63430008140033", "devdoc": { "details": "This contract is the implementation. It is meant to be used through proxy clone.", "kind": "dev", @@ -228,7 +235,7 @@ "storageLayout": { "storage": [ { - "astId": 1989, + "astId": 2859, "contract": "contracts/P256Signer.sol:P256Signer", "label": "initialized", "offset": 0, @@ -236,7 +243,7 @@ "type": "t_bool" }, { - "astId": 1992, + "astId": 2862, "contract": "contracts/P256Signer.sol:P256Signer", "label": "x", "offset": 0, @@ -244,7 +251,7 @@ "type": "t_uint256" }, { - "astId": 1995, + "astId": 2865, "contract": "contracts/P256Signer.sol:P256Signer", "label": "y", "offset": 0, diff --git a/deployments/redstone_holesky_production/P256SignerFactory.json b/deployments/redstone_holesky_production/P256SignerFactory.json index a87f3bf..bd4aa17 100644 --- a/deployments/redstone_holesky_production/P256SignerFactory.json +++ b/deployments/redstone_holesky_production/P256SignerFactory.json @@ -1,5 +1,5 @@ { - "address": "0x432870e7E5DBB4dF79f92aD0FA0FeF10f3b71219", + "address": "0x73dA77F0f2daaa88b908413495d3D0e37458212e", "abi": [ { "inputs": [ @@ -75,7 +75,7 @@ "type": "function" } ], - "transactionHash": "0x296c2f4e0032be905901a64e9742cdb096f0d7bef4be07aa8783d636aee1fc9e", + "transactionHash": "0xa0b1082f0f59348df49b04c498c9754067c39b52f903403cc605c96972b2830b", "receipt": { "to": "0x51498fd8a6218bab7eC4286642DE2E194274Cd59", "from": "0x65245F19c92ac5Adce53244406Ad126398EF203A", @@ -83,22 +83,22 @@ "transactionIndex": 1, "gasUsed": "195400", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x8f2658ce0a3d56bbab02711603bceb0a1f39b032f36d53ead8f5c26efc44110b", - "transactionHash": "0x296c2f4e0032be905901a64e9742cdb096f0d7bef4be07aa8783d636aee1fc9e", + "blockHash": "0xf6a48cdd3056cb4545227a6381e2f78efb69f127138fb5b3e6a0877d771ab305", + "transactionHash": "0xa0b1082f0f59348df49b04c498c9754067c39b52f903403cc605c96972b2830b", "logs": [], - "blockNumber": 1848292, - "cumulativeGasUsed": "259365", + "blockNumber": 2578751, + "cumulativeGasUsed": "242301", "status": 1, "byzantium": true }, "args": [ - "0x259a123DBb8461f82fa1ed539BA8678e52d3Bda8" + "0x71558e9Ac314B17Eb665441aFF60914EAE391712" ], - "numDeployments": 2, - "solcInputHash": "9a239a13792e7e509c47a689d8b7e7c4", - "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.20;\\n\\nimport {Base64Url} from \\\"./utils/Base64Url.sol\\\";\\nimport {FCL_Elliptic_ZZ} from \\\"./FCL_elliptic.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 // 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_verify(message, rs, Q);\\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_Elliptic_ZZ.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\":\"0x78658514b1f160f17b8408bddc3615b2bfaf83a50c874cdfba26ce90528214b4\",\"license\":\"MIT\"},\"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.20;\\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) public 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 || x == p || 0 == y || 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.\\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\\n (x0, y0, zz0, zzz0) = ecZZ_AddN(x0, y0, 1, 1, x1, y1);\\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); //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 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 * @dev ECDSA verification, given , signature, and public key.\\n */\\n function ecdsa_verify(bytes32 message, uint256[2] calldata rs, uint256[2] calldata Q) internal view returns (bool) {\\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 uint256 Q0 = Q[0];\\n uint256 Q1 = Q[1];\\n if (!ecAff_isOnCurve(Q0, Q1)) {\\n return false;\\n }\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 scalar_u = mulmod(uint256(message), sInv, n);\\n uint256 scalar_v = mulmod(r, sInv, n);\\n uint256 x1;\\n\\n x1 = ecZZ_mulmuladd_S_asm(Q0, Q1, scalar_u, scalar_v);\\n\\n assembly {\\n x1 := addmod(x1, sub(n, r), n)\\n }\\n //return true;\\n return x1 == 0;\\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 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 bytecode assumed to be correct\\n if (!isOnCurve(Q[0], Q[1])) {\\n return false;\\n }*/\\n\\n uint256 sInv = FCL_nModInv(s);\\n\\n uint256 X;\\n\\n //Shamir 8 dimensions\\n X = ecZZ_mulmuladd_S8_extcode(mulmod(uint256(message), sInv, n), mulmod(r, sInv, n), Shamir8);\\n\\n assembly {\\n X := addmod(X, sub(n, r), n)\\n }\\n\\n return X == 0;\\n } //end ecdsa_precomputed_verify()\\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 function ec_recover_r1(uint256 h, uint256 v, uint256 r, uint256 s) public view returns (address)\\n {\\n if (r == 0 || r >= n || s == 0 || s >= n) {\\n return address(0);\\n }\\n uint256 y=ec_Decompress(r, v-27);\\n uint256 rinv=FCL_nModInv(r);\\n uint256 u1=mulmod(n-addmod(0,h,n), rinv,n);//-hr^-1\\n uint256 u2=mulmod(s, rinv,n);//sr^-1\\n\\n uint256 Qx;\\n uint256 Qy;\\n (Qx,Qy)=ecZZ_mulmuladd(r,y, u1, u2);\\n\\n return address(uint160(uint256(keccak256(abi.encodePacked(Qx, Qy)))));\\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) public view returns(uint256 r, uint256 s)\\n {\\n r=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, n); \\n s=mulmod(FCL_nModInv(k), addmod(uint256(message), mulmod(r, kpriv, n),n),n);//s=k^-1.(h+r.kpriv)\\n\\n \\n if(r==0||s==0){\\n revert();\\n }\\n\\n\\n }\\n\\n} //EOF\\n\",\"keccak256\":\"0xd6c3e555eae02916f6b9d65db6509d7ddf0fd76d5399e29dbc1502e0b7d992a6\",\"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/FCL/WrapperFCLWebAuthn.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {FCL_WebAuthn} from \\\"FreshCryptoLib/FCL_Webauthn.sol\\\";\\n\\n/// @title WrapperFCLWebAuthn\\n/// @notice A library used to verify ECDSA signatures over secp256r1 through\\n/// EIP-1271 of Webauthn payloads.\\n/// @dev This lib is only a wrapper around the FCL_WebAuthn library.\\n/// It is meant to be used with 1271 signatures.\\n/// The wrapping is necessary because the FCL_WebAuthn has only internal\\n/// functions and use calldata. This makes it impossible to use it with\\n/// isValidSignature that use memory.\\nlibrary WrapperFCLWebAuthn {\\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 ) external view returns (bool) {\\n return FCL_WebAuthn.checkSignature(\\n authenticatorData,\\n authenticatorDataFlagMask,\\n clientData,\\n clientChallenge,\\n clientChallengeDataOffset,\\n rs,\\n Q\\n );\\n }\\n}\",\"keccak256\":\"0x21b11feafba10e0db2399a46a1d5d30a93c39d0f1c384f43ac43f4988b5d0586\"},\"contracts/P256Signer.sol\":{\"content\":\"pragma solidity ^0.8.0;\\n\\nimport {WrapperFCLWebAuthn} from \\\"./FCL/WrapperFCLWebAuthn.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 memory _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 memory _signature) public view returns (bytes4) {\\n _validate(_hash, _signature);\\n return OLD_EIP1271_MAGICVALUE;\\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 memory _signature) private view {\\n bytes32 _hash = keccak256(data);\\n (bytes memory authenticatorData, bytes memory clientData, uint256 challengeOffset, uint256[2] memory rs) =\\n abi.decode(_signature, (bytes, bytes, uint256, uint256[2]));\\n\\n bool valid = WrapperFCLWebAuthn.checkSignature(authenticatorData, 0x01, clientData, _hash, challengeOffset, rs, [x, y]);\\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\":\"0x1c4a4a8793dd4753832bd31e0a048b87ca2ef9f35b16ee4ee960eca473a4920a\"},\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea2646970667358221220d58b58802d5c7747f06cdad3d5dae1daf849ad475c9f80c8a469c68e8b50b75264736f6c63430008140033", + "numDeployments": 3, + "solcInputHash": "c99418166b2fc7a84fdc0f742530dbd8", + "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\\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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\\n let T4 := mulmod(3, y2, p) //M\\n\\n zzz := mulmod(TT1, 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\":\"0xa09802f3ca65d654d56260f40db449f9fbefbadb64429772e6f133ad6370eab9\",\"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": "0x60a060405234801561001057600080fd5b5060405161031a38038061031a83398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161028a610090600039600081816040015260d7015261028a6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b5780639f7b45791461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610062610099366004610232565b60008083836040516020016100b8929190918252602082015260400190565b60405160208183030381529060405280519060200120905060006100fc7f0000000000000000000000000000000000000000000000000000000000000000836101db565b6040517fe4a30116000000000000000000000000000000000000000000000000000000008152600481018790526024810186905290915073ffffffffffffffffffffffffffffffffffffffff82169063e4a3011690604401600060405180830381600087803b15801561016e57600080fd5b505af1158015610182573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681528692508791507f33b61205835e3063eb8935cac4b29d7fc333ad80d6cb11893ba4758adf8cdde19060200160405180910390a3949350505050565b60006c5af43d3d93803e602a57fd5bf36021528260145273602c3d8160093d39f33d3d3d3d363d3d37363d73600052816035600c6000f59050806102275763301164256000526004601cfd5b600060215292915050565b6000806040838503121561024557600080fd5b5050803592602090910135915056fea264697066735822122071f53aa036351be28c2415d8e5721596cc980c32c199aac9af70658e7c86902d64736f6c63430008140033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/redstone_holesky_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json b/deployments/redstone_holesky_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.json new file mode 100644 index 0000000..fdb6b70 --- /dev/null +++ b/deployments/redstone_holesky_production/solcInputs/c99418166b2fc7a84fdc0f742530dbd8.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\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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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 := addmod(X, zz, p) //X+ZZ\n let TT1 := addmod(X, sub(p, zz), p) //X-ZZ\n y2 := mulmod(y2, TT1, p) //(X-ZZ)(X+ZZ)\n let T4 := mulmod(3, y2, p) //M\n\n zzz := mulmod(TT1, 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