diff --git a/contracts/utils/cryptography/SignatureChecker.sol b/contracts/utils/cryptography/SignatureChecker.sol index de619568990..121229fe1ef 100644 --- a/contracts/utils/cryptography/SignatureChecker.sol +++ b/contracts/utils/cryptography/SignatureChecker.sol @@ -50,7 +50,7 @@ library SignatureChecker { (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecoverCalldata(hash, signature); return err == ECDSA.RecoverError.NoError && recovered == signer; } else { - return isValidERC1271SignatureNow(signer, hash, signature); + return isValidERC1271SignatureNowCalldata(signer, hash, signature); } } @@ -73,8 +73,8 @@ library SignatureChecker { // Encoded calldata is : // [ 0x00 - 0x03 ] // [ 0x04 - 0x23 ] - // [ 0x24 - 0x44 ] (0x40) - // [ 0x44 - 0x64 ] + // [ 0x24 - 0x43 ] (0x40) + // [ 0x44 - 0x63 ] // [ 0x64 - ... ] let ptr := mload(0x40) mstore(ptr, selector) @@ -87,6 +87,33 @@ library SignatureChecker { } } + function isValidERC1271SignatureNowCalldata( + address signer, + bytes32 hash, + bytes calldata signature + ) internal view returns (bool result) { + bytes4 selector = IERC1271.isValidSignature.selector; + + assembly ("memory-safe") { + // Encoded calldata is : + // [ 0x00 - 0x03 ] + // [ 0x04 - 0x23 ] + // [ 0x24 - 0x43 ] (0x40) + // [ 0x44 - 0x63 ] + // [ 0x64 - ... ] + let ptr := mload(0x40) + mstore(ptr, selector) + mstore(add(ptr, 0x04), hash) + mstore(add(ptr, 0x24), 0x40) + let length := signature.length + mstore(add(ptr, 0x44), length) + calldatacopy(add(ptr, 0x64), signature.offset, length) + + let success := staticcall(gas(), signer, ptr, add(length, 0x64), 0x00, 0x20) + result := and(success, and(gt(returndatasize(), 0x1f), eq(mload(0x00), selector))) + } + } + /** * @dev Verifies a signature for a given ERC-7913 signer and hash. *