From 4107dd21433bb45be24957fe8e64096a00efdcf5 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Fri, 1 Sep 2023 16:01:25 +0100 Subject: [PATCH 1/4] Decode calldata for existing lib interface (WIP) - Stack Too Deep --- .../safe/src/SafeWebAuthnPlugin.sol | 168 +++++++++++++++--- .../safe/src/lib/FCL_Webauthn.sol | 8 +- .../safe/test/forge/utils/TestHelper.sol | 6 + .../integration/SafeWebAuthnPlugin.test.ts | 2 +- 4 files changed, 159 insertions(+), 25 deletions(-) diff --git a/account-integrations/safe/src/SafeWebAuthnPlugin.sol b/account-integrations/safe/src/SafeWebAuthnPlugin.sol index 28f3935f..4df9ffb1 100644 --- a/account-integrations/safe/src/SafeWebAuthnPlugin.sol +++ b/account-integrations/safe/src/SafeWebAuthnPlugin.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; +// import "forge-std/Test.sol"; + import {BaseAccount} from "account-abstraction/contracts/core/BaseAccount.sol"; import {IEntryPoint, UserOperation} from "account-abstraction/contracts/interfaces/IEntryPoint.sol"; @@ -71,31 +73,157 @@ contract SafeWebAuthnPlugin is BaseAccount { UserOperation calldata userOp, bytes32 userOpHash ) internal override returns (uint256 validationData) { + // console2.logBytes(userOp.signature); + bytes calldata authenticatorData; + bytes1 authenticatorDataFlagMask; + bytes calldata clientData; + uint256 clientChallengeDataOffset; + uint256[2] calldata signature; + uint256[2] calldata pubKey; + { - ( - bytes memory authenticatorData, - bytes1 authenticatorDataFlagMask, - bytes memory clientData, - uint256 clientChallengeDataOffset, - uint256[2] memory signature, - uint256[2] memory pubKey - ) = abi.decode( - userOp.signature, - (bytes, bytes1, bytes, uint256, uint256[2], uint256[2]) - ); + uint256 i = 0; + uint256 dataLen; + uint256 paramLen; + + // parse length of all fixed-length params (including length) + dataLen = 32; + paramLen = abi.decode(userOp.signature[i:i+dataLen+1], (uint256)); + // console2.logString("PARAM LEN"); + // console2.logUint(paramLen); + // Fixed-length params (bytes1, (uint256?), uint256, uint256[2], uint256[2]). Expect 8 slots = 256 bytes + i += dataLen; // advance index + - bool verified = FCL_WebAuthn.checkSignature( - authenticatorData, + // decode fixed length params (values to memory) + dataLen = 3 * 32; //lenFixedParams - 32; // -32 already read length + ( authenticatorDataFlagMask, - clientData, - userOpHash, - clientChallengeDataOffset, - signature, - pubKey + , // some number + clientChallengeDataOffset + ) = abi.decode( + userOp.signature[i:i+dataLen+1], + ( + bytes1, + uint256, //not sure what is encoded here + uint256 + ) ); - if (!verified) return SIG_VALIDATION_FAILED; - return 0; + i += dataLen; // advance index + // console2.logString("FIXED COPY"); + // console2.log(uint8(authenticatorDataFlagMask)); + // console2.log("%x", clientChallengeDataOffset); + + + bytes calldata calldataLocation; + // load fixed length array params (pointers to calldata) + dataLen = 2 * 32; + calldataLocation = userOp.signature[i:i+dataLen+1]; + assembly{ + signature := calldataLocation.offset + } + i += dataLen; // advance index + + calldataLocation = userOp.signature[i:i+dataLen+1]; + assembly{ + pubKey := calldataLocation.offset + } + i += dataLen; // advance index + // console2.logString("FIXED CALLDATA"); + // console2.log("%x, %x", signature[0], signature[1]); + // console2.log("%x, %x", pubKey[0], pubKey[1]); + + // parse length of authenticatorData + dataLen = 32; + paramLen = abi.decode(userOp.signature[i:i+dataLen+1], (uint256)); + // i += dataLen; // advance index + // assign authenticatorData to sig splice + // dataLen = paramLen; + dataLen = ((paramLen >> 5) + 1) << 5; // (round up to next slot) + authenticatorData = userOp.signature[i:i+dataLen+1]; + // console2.logString("auth data"); + // console2.logBytes(authenticatorData); + // i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) + i += dataLen; + + // parse length of clientData + dataLen = 32; + paramLen = abi.decode(userOp.signature[i:i+dataLen+1], (uint256)); + // i += dataLen; // advance index + // assign clientData to sig splice + // dataLen = paramLen; + dataLen = ((paramLen >> 5) + 1) << 5; // (round up to next slot) + clientData = userOp.signature[i:i+dataLen+1]; + // console2.logString("client data"); + // console2.logBytes(clientData); + // i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) + i += dataLen; } +/* + 0000000000000000000000000000000000000000000000000000000000000100 // 256 = 8 x 32 slots + + 0100000000000000000000000000000000000000000000000000000000000000 // authenticatorDataFlagMask + + 0000000000000000000000000000000000000000000000000000000000000160 // 352? + + 0000000000000000000000000000000000000000000000000000000000000024 // clientChallengeDataOffset + + 515562d3cb505fff416437050b64d207a4935c42ff3ddda1ac3ac70fcc3424f5 + 85f7cf6ac11bcf378b7dcdffbfc74afc38b59438fa60690745d064b1de74ba01 + + bbe2ce868d703d08aab8866f2565c6c3eea7bccb3198a7c8056a317ea26ab7f1 + 90766bfd35b6502e5a989d4cbc4c8bc651bbf95bfc8dff137f4981c9162d7342 + + 0000000000000000000000000000000000000000000000000000000000000025 // 37 bytes + 1584482fdf7a4d0b7eb9d45cf835288cb59e55b8249fff356e33be88ecc546d1 + 1d00000000000000000000000000000000000000000000000000000000000000 + ########## + + 0000000000000000000000000000000000000000000000000000000000000092 // 146 bytes + 7b2274797065223a22776562617574686e2e676574222c226368616c6c656e67 + 65223a22efbfbd22efbfbd5f21efbfbd1b113e63efbfbdefbfbd6defbfbd4fef // 64 + bfbdefbfbd11efbfbd11efbfbd40efbfbdefbfbdefbfbd64efbfbdefbfbd3cef + bfbd58222c226f726967696e223a2268747470733a2f2f646576656c6f706d65 // 128 + 6e742e666f72756d64616f732e636f6d227d0000000000000000000000000000 // +18 + #################################### +*/ + + // ( + // bytes calldata authenticatorData, + // bytes1 authenticatorDataFlagMask, + // bytes calldata clientData, + // uint256 clientChallengeDataOffset, + // uint256[2] calldata signature, + // uint256[2] calldata pubKey + // ) = abi.decode( + // userOp.signature, + // (bytes, bytes1, bytes, uint256, uint256[2], uint256[2]) + // ); + + // ( + // bytes memory authenticatorData, + // bytes1 authenticatorDataFlagMask, + // bytes memory clientData, + // uint256 clientChallengeDataOffset, + // uint256[2] memory signature, + // uint256[2] memory pubKey + // ) = abi.decode( + // userOp.signature, + // (bytes, bytes1, bytes, uint256, uint256[2], uint256[2]) + // ); + + bool verified = FCL_WebAuthn.checkSignature( + authenticatorData, + authenticatorDataFlagMask, + clientData, + userOpHash, + clientChallengeDataOffset, + signature, + pubKey + ); + // bool verified = true; + if (!verified) return SIG_VALIDATION_FAILED; + return 0; } /** diff --git a/account-integrations/safe/src/lib/FCL_Webauthn.sol b/account-integrations/safe/src/lib/FCL_Webauthn.sol index 8c40becf..c4bfe9d6 100644 --- a/account-integrations/safe/src/lib/FCL_Webauthn.sol +++ b/account-integrations/safe/src/lib/FCL_Webauthn.sol @@ -76,13 +76,13 @@ library FCL_WebAuthn { /** @notice Modified from original Fresh Crypto Lib code to use memory instead of calldata */ function checkSignature( - bytes memory authenticatorData, + bytes calldata authenticatorData, bytes1 authenticatorDataFlagMask, - bytes memory clientData, + bytes calldata clientData, bytes32 clientChallenge, uint256 clientChallengeDataOffset, - uint256[2] memory rs, - uint256[2] memory Q + uint256[2] calldata rs, + uint256[2] calldata Q ) internal returns (bool) { // Let the caller check if User Presence (0x01) or User Verification (0x04) are set diff --git a/account-integrations/safe/test/forge/utils/TestHelper.sol b/account-integrations/safe/test/forge/utils/TestHelper.sol index 08e4b7dc..b77feaa0 100644 --- a/account-integrations/safe/test/forge/utils/TestHelper.sol +++ b/account-integrations/safe/test/forge/utils/TestHelper.sol @@ -118,5 +118,11 @@ abstract contract TestHelper is Test { signature, publicKey ); + // console2.logString("authenticatorData"); + // console2.logBytes(authenticatorData); + // console2.logString("flagMask"); + // console2.logBytes1(authenticatorDataFlagMask); + // console2.logString("userOp"); + // console2.logBytes(userOpSignature); } } diff --git a/account-integrations/safe/test/hardhat/integration/SafeWebAuthnPlugin.test.ts b/account-integrations/safe/test/hardhat/integration/SafeWebAuthnPlugin.test.ts index 0ad7e31c..a4c4044f 100644 --- a/account-integrations/safe/test/hardhat/integration/SafeWebAuthnPlugin.test.ts +++ b/account-integrations/safe/test/hardhat/integration/SafeWebAuthnPlugin.test.ts @@ -75,7 +75,7 @@ describe("SafeWebAuthnPlugin", () => { const clientData = "0x7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22efbfbd22efbfbd5f21efbfbd1b113e63efbfbdefbfbd6defbfbd4fefbfbdefbfbd11efbfbd11efbfbd40efbfbdefbfbdefbfbd64efbfbdefbfbd3cefbfbd58222c226f726967696e223a2268747470733a2f2f646576656c6f706d656e742e666f72756d64616f732e636f6d227d"; const clientChallengeDataOffset = 36; - const signature = [ + const signature: [BigNumberish, BigNumberish] = [ BigInt( "36788204816852931931532076736929768488646494203674172515272861180041446565109" ), From d48671cc9c5d2050217aec3667352bd325ea58f3 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Thu, 14 Sep 2023 18:10:15 +0100 Subject: [PATCH 2/4] Reduce stack depth (WIP) --- .../safe/src/SafeWebAuthnPlugin.sol | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/account-integrations/safe/src/SafeWebAuthnPlugin.sol b/account-integrations/safe/src/SafeWebAuthnPlugin.sol index 4df9ffb1..6b74bc03 100644 --- a/account-integrations/safe/src/SafeWebAuthnPlugin.sol +++ b/account-integrations/safe/src/SafeWebAuthnPlugin.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; -// import "forge-std/Test.sol"; +import "forge-std/Test.sol"; import {BaseAccount} from "account-abstraction/contracts/core/BaseAccount.sol"; import {IEntryPoint, UserOperation} from "account-abstraction/contracts/interfaces/IEntryPoint.sol"; @@ -69,40 +69,41 @@ contract SafeWebAuthnPlugin is BaseAccount { return _publicKey; } + struct LocalVarStruct { + bytes1 authenticatorDataFlagMask; + uint256 clientChallengeDataOffset; + } + function _validateSignature( UserOperation calldata userOp, bytes32 userOpHash ) internal override returns (uint256 validationData) { - // console2.logBytes(userOp.signature); + console2.logString("SIG"); + console2.logBytes(userOp.signature); bytes calldata authenticatorData; - bytes1 authenticatorDataFlagMask; bytes calldata clientData; - uint256 clientChallengeDataOffset; uint256[2] calldata signature; uint256[2] calldata pubKey; + LocalVarStruct memory s; - { - uint256 i = 0; - uint256 dataLen; - uint256 paramLen; - + { // parse length of all fixed-length params (including length) - dataLen = 32; - paramLen = abi.decode(userOp.signature[i:i+dataLen+1], (uint256)); - // console2.logString("PARAM LEN"); - // console2.logUint(paramLen); + uint i = 0; + uint dataLen = 32; + uint256 paramLen = abi.decode(userOp.signature[i:i+dataLen], (uint256)); + console2.logString("PARAM LEN"); + console2.logUint(paramLen); // Fixed-length params (bytes1, (uint256?), uint256, uint256[2], uint256[2]). Expect 8 slots = 256 bytes i += dataLen; // advance index - // decode fixed length params (values to memory) dataLen = 3 * 32; //lenFixedParams - 32; // -32 already read length ( - authenticatorDataFlagMask, + s.authenticatorDataFlagMask, , // some number - clientChallengeDataOffset + s.clientChallengeDataOffset ) = abi.decode( - userOp.signature[i:i+dataLen+1], + userOp.signature[i:i+dataLen], ( bytes1, uint256, //not sure what is encoded here @@ -110,52 +111,61 @@ contract SafeWebAuthnPlugin is BaseAccount { ) ); i += dataLen; // advance index - // console2.logString("FIXED COPY"); - // console2.log(uint8(authenticatorDataFlagMask)); - // console2.log("%x", clientChallengeDataOffset); + console2.logString("FIXED COPY"); + console2.log(uint8(s.authenticatorDataFlagMask)); + console2.log("%x", s.clientChallengeDataOffset); bytes calldata calldataLocation; // load fixed length array params (pointers to calldata) dataLen = 2 * 32; - calldataLocation = userOp.signature[i:i+dataLen+1]; + calldataLocation = userOp.signature[i:i+dataLen]; assembly{ signature := calldataLocation.offset } i += dataLen; // advance index - calldataLocation = userOp.signature[i:i+dataLen+1]; + calldataLocation = userOp.signature[i:i+dataLen]; assembly{ pubKey := calldataLocation.offset } i += dataLen; // advance index - // console2.logString("FIXED CALLDATA"); - // console2.log("%x, %x", signature[0], signature[1]); - // console2.log("%x, %x", pubKey[0], pubKey[1]); + console2.logString("FIXED CALLDATA"); + console2.log("%x, %x", signature[0], signature[1]); + console2.log("%x, %x", pubKey[0], pubKey[1]); // parse length of authenticatorData dataLen = 32; - paramLen = abi.decode(userOp.signature[i:i+dataLen+1], (uint256)); + paramLen = abi.decode(userOp.signature[i:i+dataLen], (uint256)); + console2.logString("AUTH LEN"); + console2.log(paramLen); // i += dataLen; // advance index // assign authenticatorData to sig splice - // dataLen = paramLen; dataLen = ((paramLen >> 5) + 1) << 5; // (round up to next slot) - authenticatorData = userOp.signature[i:i+dataLen+1]; - // console2.logString("auth data"); - // console2.logBytes(authenticatorData); + dataLen += 32; //include index + console2.logString("AUTH DATALEN"); + console2.log(dataLen); + + authenticatorData = userOp.signature[i:i+dataLen]; + console2.logString("AUTH DATA"); + console2.logBytes(authenticatorData); // i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) i += dataLen; // parse length of clientData dataLen = 32; - paramLen = abi.decode(userOp.signature[i:i+dataLen+1], (uint256)); + paramLen = abi.decode(userOp.signature[i:i+dataLen], (uint256)); + console2.logString("CLIENT LEN"); + console2.log(paramLen); // i += dataLen; // advance index // assign clientData to sig splice - // dataLen = paramLen; dataLen = ((paramLen >> 5) + 1) << 5; // (round up to next slot) - clientData = userOp.signature[i:i+dataLen+1]; - // console2.logString("client data"); - // console2.logBytes(clientData); + dataLen += 32; + console2.logString("CLIENT DATALEN"); + console2.log(dataLen); + clientData = userOp.signature[i:i+dataLen]; + console2.logString("CLIENT DATA"); + console2.logBytes(clientData); // i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) i += dataLen; } @@ -214,14 +224,13 @@ contract SafeWebAuthnPlugin is BaseAccount { bool verified = FCL_WebAuthn.checkSignature( authenticatorData, - authenticatorDataFlagMask, + s.authenticatorDataFlagMask, clientData, userOpHash, - clientChallengeDataOffset, + s.clientChallengeDataOffset, signature, pubKey ); - // bool verified = true; if (!verified) return SIG_VALIDATION_FAILED; return 0; } From 43e530d4f403429b97dc6d1688e3c8361117a032 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Thu, 14 Sep 2023 18:21:08 +0100 Subject: [PATCH 3/4] Read calldata bytes (WIP) - Logs --- .../safe/src/SafeWebAuthnPlugin.sol | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/account-integrations/safe/src/SafeWebAuthnPlugin.sol b/account-integrations/safe/src/SafeWebAuthnPlugin.sol index 6b74bc03..6a64a522 100644 --- a/account-integrations/safe/src/SafeWebAuthnPlugin.sol +++ b/account-integrations/safe/src/SafeWebAuthnPlugin.sol @@ -139,35 +139,31 @@ contract SafeWebAuthnPlugin is BaseAccount { paramLen = abi.decode(userOp.signature[i:i+dataLen], (uint256)); console2.logString("AUTH LEN"); console2.log(paramLen); - // i += dataLen; // advance index + i += dataLen; // advance index // assign authenticatorData to sig splice - dataLen = ((paramLen >> 5) + 1) << 5; // (round up to next slot) - dataLen += 32; //include index + dataLen = paramLen;//((paramLen >> 5) + 1) << 5; // (round up to next slot) console2.logString("AUTH DATALEN"); console2.log(dataLen); authenticatorData = userOp.signature[i:i+dataLen]; console2.logString("AUTH DATA"); console2.logBytes(authenticatorData); - // i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) - i += dataLen; + i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) // parse length of clientData dataLen = 32; paramLen = abi.decode(userOp.signature[i:i+dataLen], (uint256)); console2.logString("CLIENT LEN"); console2.log(paramLen); - // i += dataLen; // advance index + i += dataLen; // advance index // assign clientData to sig splice - dataLen = ((paramLen >> 5) + 1) << 5; // (round up to next slot) - dataLen += 32; + dataLen = paramLen;// ((paramLen >> 5) + 1) << 5; // (round up to next slot) console2.logString("CLIENT DATALEN"); console2.log(dataLen); clientData = userOp.signature[i:i+dataLen]; console2.logString("CLIENT DATA"); console2.logBytes(clientData); - // i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) - i += dataLen; + i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) } /* 0000000000000000000000000000000000000000000000000000000000000100 // 256 = 8 x 32 slots From eb8f46df3df2f70bebd9ece81cb622f860769f4a Mon Sep 17 00:00:00 2001 From: James Zaki Date: Thu, 14 Sep 2023 18:24:19 +0100 Subject: [PATCH 4/4] Fix WebAuthn test using unmodified lib --- .../safe/src/SafeWebAuthnPlugin.sol | 76 ------------------- 1 file changed, 76 deletions(-) diff --git a/account-integrations/safe/src/SafeWebAuthnPlugin.sol b/account-integrations/safe/src/SafeWebAuthnPlugin.sol index 6a64a522..40ade6d0 100644 --- a/account-integrations/safe/src/SafeWebAuthnPlugin.sol +++ b/account-integrations/safe/src/SafeWebAuthnPlugin.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.0 <0.9.0; -import "forge-std/Test.sol"; - import {BaseAccount} from "account-abstraction/contracts/core/BaseAccount.sol"; import {IEntryPoint, UserOperation} from "account-abstraction/contracts/interfaces/IEntryPoint.sol"; @@ -78,8 +76,6 @@ contract SafeWebAuthnPlugin is BaseAccount { UserOperation calldata userOp, bytes32 userOpHash ) internal override returns (uint256 validationData) { - console2.logString("SIG"); - console2.logBytes(userOp.signature); bytes calldata authenticatorData; bytes calldata clientData; uint256[2] calldata signature; @@ -91,8 +87,6 @@ contract SafeWebAuthnPlugin is BaseAccount { uint i = 0; uint dataLen = 32; uint256 paramLen = abi.decode(userOp.signature[i:i+dataLen], (uint256)); - console2.logString("PARAM LEN"); - console2.logUint(paramLen); // Fixed-length params (bytes1, (uint256?), uint256, uint256[2], uint256[2]). Expect 8 slots = 256 bytes i += dataLen; // advance index @@ -111,9 +105,6 @@ contract SafeWebAuthnPlugin is BaseAccount { ) ); i += dataLen; // advance index - console2.logString("FIXED COPY"); - console2.log(uint8(s.authenticatorDataFlagMask)); - console2.log("%x", s.clientChallengeDataOffset); bytes calldata calldataLocation; @@ -130,93 +121,26 @@ contract SafeWebAuthnPlugin is BaseAccount { pubKey := calldataLocation.offset } i += dataLen; // advance index - console2.logString("FIXED CALLDATA"); - console2.log("%x, %x", signature[0], signature[1]); - console2.log("%x, %x", pubKey[0], pubKey[1]); // parse length of authenticatorData dataLen = 32; paramLen = abi.decode(userOp.signature[i:i+dataLen], (uint256)); - console2.logString("AUTH LEN"); - console2.log(paramLen); i += dataLen; // advance index // assign authenticatorData to sig splice dataLen = paramLen;//((paramLen >> 5) + 1) << 5; // (round up to next slot) - console2.logString("AUTH DATALEN"); - console2.log(dataLen); authenticatorData = userOp.signature[i:i+dataLen]; - console2.logString("AUTH DATA"); - console2.logBytes(authenticatorData); i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) // parse length of clientData dataLen = 32; paramLen = abi.decode(userOp.signature[i:i+dataLen], (uint256)); - console2.logString("CLIENT LEN"); - console2.log(paramLen); i += dataLen; // advance index // assign clientData to sig splice dataLen = paramLen;// ((paramLen >> 5) + 1) << 5; // (round up to next slot) - console2.logString("CLIENT DATALEN"); - console2.log(dataLen); clientData = userOp.signature[i:i+dataLen]; - console2.logString("CLIENT DATA"); - console2.logBytes(clientData); i += ((dataLen >> 5) + 1) << 5; // advance index (round up to next slot) } -/* - 0000000000000000000000000000000000000000000000000000000000000100 // 256 = 8 x 32 slots - - 0100000000000000000000000000000000000000000000000000000000000000 // authenticatorDataFlagMask - - 0000000000000000000000000000000000000000000000000000000000000160 // 352? - - 0000000000000000000000000000000000000000000000000000000000000024 // clientChallengeDataOffset - - 515562d3cb505fff416437050b64d207a4935c42ff3ddda1ac3ac70fcc3424f5 - 85f7cf6ac11bcf378b7dcdffbfc74afc38b59438fa60690745d064b1de74ba01 - - bbe2ce868d703d08aab8866f2565c6c3eea7bccb3198a7c8056a317ea26ab7f1 - 90766bfd35b6502e5a989d4cbc4c8bc651bbf95bfc8dff137f4981c9162d7342 - - 0000000000000000000000000000000000000000000000000000000000000025 // 37 bytes - 1584482fdf7a4d0b7eb9d45cf835288cb59e55b8249fff356e33be88ecc546d1 - 1d00000000000000000000000000000000000000000000000000000000000000 - ########## - - 0000000000000000000000000000000000000000000000000000000000000092 // 146 bytes - 7b2274797065223a22776562617574686e2e676574222c226368616c6c656e67 - 65223a22efbfbd22efbfbd5f21efbfbd1b113e63efbfbdefbfbd6defbfbd4fef // 64 - bfbdefbfbd11efbfbd11efbfbd40efbfbdefbfbdefbfbd64efbfbdefbfbd3cef - bfbd58222c226f726967696e223a2268747470733a2f2f646576656c6f706d65 // 128 - 6e742e666f72756d64616f732e636f6d227d0000000000000000000000000000 // +18 - #################################### -*/ - - // ( - // bytes calldata authenticatorData, - // bytes1 authenticatorDataFlagMask, - // bytes calldata clientData, - // uint256 clientChallengeDataOffset, - // uint256[2] calldata signature, - // uint256[2] calldata pubKey - // ) = abi.decode( - // userOp.signature, - // (bytes, bytes1, bytes, uint256, uint256[2], uint256[2]) - // ); - - // ( - // bytes memory authenticatorData, - // bytes1 authenticatorDataFlagMask, - // bytes memory clientData, - // uint256 clientChallengeDataOffset, - // uint256[2] memory signature, - // uint256[2] memory pubKey - // ) = abi.decode( - // userOp.signature, - // (bytes, bytes1, bytes, uint256, uint256[2], uint256[2]) - // ); bool verified = FCL_WebAuthn.checkSignature( authenticatorData,