From 92317f2579ef9b53ae8b142bc0e0aebad14aec4c Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 9 Dec 2024 12:05:15 +0000 Subject: [PATCH 1/4] Minimal ERC6492 non-reverting verifier --- src/utils/SignatureCheckerLib.sol | 34 ++++++++++++++++++------------- test/SignatureCheckerLib.t.sol | 15 ++++++++++++++ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/utils/SignatureCheckerLib.sol b/src/utils/SignatureCheckerLib.sol index 531d79354..e3aff172f 100644 --- a/src/utils/SignatureCheckerLib.sol +++ b/src/utils/SignatureCheckerLib.sol @@ -303,6 +303,7 @@ library SignatureCheckerLib { /// If the signature is postfixed with the ERC6492 magic number, it will attempt to /// deploy / prepare the `signer` smart account before doing a regular ERC1271 check. /// Note: This function is NOT reentrancy safe. + /// See: https://gist.github.com/Vectorized/011d6becff6e0a73e42fe100f8d7ef04 function isValidERC6492SignatureNowAllowSideEffects( address signer, bytes32 hash, @@ -329,21 +330,26 @@ library SignatureCheckerLib { if iszero(noCode) { isValid := callIsValidSignature(signer, hash, signature) } break } - let o := add(signature, 0x20) // Signature bytes. - let d := add(o, mload(add(o, 0x20))) // Factory calldata. - if noCode { - if iszero(call(gas(), mload(o), 0, add(d, 0x20), mload(d), codesize(), 0x00)) { - break - } - } - let s := add(o, mload(add(o, 0x40))) // Inner signature. - isValid := callIsValidSignature(signer, hash, s) - if iszero(isValid) { - if call(gas(), mload(o), 0, add(d, 0x20), mload(d), codesize(), 0x00) { - noCode := iszero(extcodesize(signer)) - if iszero(noCode) { isValid := callIsValidSignature(signer, hash, s) } - } + if iszero(noCode) { + let o := add(signature, 0x20) // Signature bytes. + isValid := callIsValidSignature(signer, hash, add(o, mload(add(o, 0x40)))) + if isValid { break } } + let m := mload(0x40) + mstore(m, signer) + mstore(add(m, 0x20), hash) + pop( + call( + gas(), // Remaining gas. + 0x0000bc370E4DC924F427d84e2f4B9Ec81626ba7E, // Verifier. + 0, // Send zero ETH. + m, // Start of memory. + add(returndatasize(), 0x40), // Length of calldata in memory. + staticcall(gas(), 4, add(signature, 0x20), n, add(m, 0x40), n), // 1. + 0x00 // Length of returndata to write. + ) + ) + isValid := returndatasize() break } // Do `ecrecover` fallback if `noCode && !isValid`. diff --git a/test/SignatureCheckerLib.t.sol b/test/SignatureCheckerLib.t.sol index a10606864..e844c9669 100644 --- a/test/SignatureCheckerLib.t.sol +++ b/test/SignatureCheckerLib.t.sol @@ -473,6 +473,7 @@ contract SignatureCheckerLibTest is SoladyTest { } function testERC6492AllowSideEffectsPostDeploy() public { + _etchERC6492Verifier(); _ERC6492TestTemps memory t = _erc6492TestTemps(); (bool success,) = t.factory.call(t.factoryCalldata); require(success); @@ -491,6 +492,7 @@ contract SignatureCheckerLibTest is SoladyTest { } function testERC6492AllowSideEffectsPreDeploy() public { + _etchERC6492Verifier(); _ERC6492TestTemps memory t = _erc6492TestTemps(); t.result = SignatureCheckerLib.isValidERC6492SignatureNowAllowSideEffects( t.smartAccount, t.digest, t.innerSignature @@ -522,6 +524,19 @@ contract SignatureCheckerLibTest is SoladyTest { assertEq(MockERC1271Wallet(t.smartAccount).signer(), t.eoa); } + function _etchERC6492Verifier() internal returns (address verifier) { + _ERC6492TestTemps memory t; + t.initcode = + hex"6040600b3d3960403df3fe36383d373d3d6020515160208051013d3d515af160203851516084018038385101606037303452813582523838523490601c34355afa34513060e01b141634f3"; + t.factory = _NICKS_FACTORY; + t.salt = 0x0000000000000000000000000000000000000000ebfa269e1c28e801a0dc87e2; + verifier = LibClone.predictDeterministicAddress(keccak256(t.initcode), t.salt, t.factory); + assertEq(_nicksCreate2(0, t.salt, t.initcode), verifier); + assertGt(verifier.code.length, 0); + emit LogBytes32(keccak256(t.initcode)); + emit LogBytes(verifier.code); + } + function _etchERC6492RevertingVerifier() internal returns (address revertingVerifier) { _ERC6492TestTemps memory t; t.initcode = From 937a3900bf7baf5c7132bf22596385461486b010 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 9 Dec 2024 12:06:22 +0000 Subject: [PATCH 2/4] Edit comments --- src/utils/SignatureCheckerLib.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/SignatureCheckerLib.sol b/src/utils/SignatureCheckerLib.sol index e3aff172f..9565b2565 100644 --- a/src/utils/SignatureCheckerLib.sol +++ b/src/utils/SignatureCheckerLib.sol @@ -303,6 +303,8 @@ library SignatureCheckerLib { /// If the signature is postfixed with the ERC6492 magic number, it will attempt to /// deploy / prepare the `signer` smart account before doing a regular ERC1271 check. /// Note: This function is NOT reentrancy safe. + /// The verifier must be deployed. + /// Otherwise, the function will return false if `signer` is not yet deployed / prepared. /// See: https://gist.github.com/Vectorized/011d6becff6e0a73e42fe100f8d7ef04 function isValidERC6492SignatureNowAllowSideEffects( address signer, From 5e9948e6bdb5d9bc14a065ea2de1387e18ed6440 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 9 Dec 2024 12:11:05 +0000 Subject: [PATCH 3/4] Edit comments --- src/utils/SignatureCheckerLib.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/SignatureCheckerLib.sol b/src/utils/SignatureCheckerLib.sol index 9565b2565..9025b201f 100644 --- a/src/utils/SignatureCheckerLib.sol +++ b/src/utils/SignatureCheckerLib.sol @@ -306,6 +306,8 @@ library SignatureCheckerLib { /// The verifier must be deployed. /// Otherwise, the function will return false if `signer` is not yet deployed / prepared. /// See: https://gist.github.com/Vectorized/011d6becff6e0a73e42fe100f8d7ef04 + /// With a dedicated verifier, this function is safe to use in contracts + /// that have been granted special permissions. function isValidERC6492SignatureNowAllowSideEffects( address signer, bytes32 hash, From cca555c569588b7244bfffcb99b3e4d093fd80aa Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 9 Dec 2024 12:11:23 +0000 Subject: [PATCH 4/4] Edit comments --- src/utils/SignatureCheckerLib.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/SignatureCheckerLib.sol b/src/utils/SignatureCheckerLib.sol index 9025b201f..5999a20b5 100644 --- a/src/utils/SignatureCheckerLib.sol +++ b/src/utils/SignatureCheckerLib.sol @@ -345,7 +345,7 @@ library SignatureCheckerLib { pop( call( gas(), // Remaining gas. - 0x0000bc370E4DC924F427d84e2f4B9Ec81626ba7E, // Verifier. + 0x0000bc370E4DC924F427d84e2f4B9Ec81626ba7E, // Non-reverting verifier. 0, // Send zero ETH. m, // Start of memory. add(returndatasize(), 0x40), // Length of calldata in memory.