From 3b8bf1080a9d86f21525371405c43034b4d8e529 Mon Sep 17 00:00:00 2001 From: David Eiber Date: Wed, 8 Nov 2023 12:26:10 -0500 Subject: [PATCH 1/3] Added 1271 wrapper --- src/Kernel.sol | 40 ++++++++++++++++++++++++--------- test/foundry/KernelTestBase.sol | 6 ++++- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/Kernel.sol b/src/Kernel.sol index 6275f5cb..6f9cb66a 100644 --- a/src/Kernel.sol +++ b/src/Kernel.sol @@ -239,25 +239,45 @@ contract Kernel is EIP712, Compatibility, KernelStorage { return _validateSignature(hash, signature); } + function _domainSeparator() internal view override returns (bytes32) { + // Obtain the name and version from the _domainNameAndVersion function. + (string memory name, string memory version) = _domainNameAndVersion(); + bytes32 nameHash = keccak256(bytes(name)); + bytes32 versionHash = keccak256(bytes(version)); + + // Use the proxy address for the EIP-712 domain separator. + address proxyAddress = address(this); + + // Construct the domain separator with name, version, chainId, and proxy address. + bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, proxyAddress)); + } + /// @notice Checks if a signature is valid /// @dev This function checks if a signature is valid based on the hash of the data signed. /// @param hash The hash of the data that was signed /// @param signature The signature to be validated /// @return The magic value 0x1626ba7e if the signature is valid, otherwise returns 0xffffffff. function isValidSignature(bytes32 hash, bytes calldata signature) public view returns (bytes4) { - ValidationData validationData = validateSignature(hash, signature); + // Include the proxy address in the domain separator + bytes32 domainSeparator = _domainSeparator(); + + // Recreate the signed message hash with the correct domain separator + bytes32 signedMessageHash = keccak256(abi.encodePacked("\x19\x01", domainSeparator, hash)); + + ValidationData validationData = validateSignature(signedMessageHash, signature); (ValidAfter validAfter, ValidUntil validUntil, address result) = parseValidationData(validationData); - if (ValidAfter.unwrap(validAfter) > block.timestamp) { - return 0xffffffff; - } - if (ValidUntil.unwrap(validUntil) < block.timestamp) { - return 0xffffffff; - } - if (result != address(0)) { + + // Check if the signature is valid within the specified time frame and the result is successful + if (ValidAfter.unwrap(validAfter) <= block.timestamp && + ValidUntil.unwrap(validUntil) >= block.timestamp && + result == address(0)) { + // If all checks pass, return the ERC1271 magic value for a valid signature + return 0x1626ba7e; + } else { + // If any check fails, return the failure magic value return 0xffffffff; } - - return 0x1626ba7e; } function _checkCaller() internal view returns (bool) { diff --git a/test/foundry/KernelTestBase.sol b/test/foundry/KernelTestBase.sol index baa2d42d..b7ccce4b 100644 --- a/test/foundry/KernelTestBase.sol +++ b/test/foundry/KernelTestBase.sol @@ -177,13 +177,17 @@ abstract contract KernelTestBase is Test { } function test_validate_signature() external { + Kernel kernel2 = Kernel(payable(factory.createAccount(address(kernelImpl), getInitializeData(), 3))); bytes32 hash = keccak256(abi.encodePacked("hello world")); - bytes memory sig = signHash(hash); + bytes32 digest = keccak256(abi.encodePacked("\x19\x01", ERC4337Utils._buildDomainSeparator("Kernel", "0.2.2", address(kernel)), hash)); + bytes memory sig = signHash(digest); assertEq(kernel.isValidSignature(hash, sig), Kernel.isValidSignature.selector); + assertEq(kernel2.isValidSignature(hash, sig), bytes4(0xffffffff)); } function test_fail_validate_wrongsignature() external { bytes32 hash = keccak256(abi.encodePacked("hello world")); + bytes32 digest = keccak256(abi.encodePacked("\x19\x01", ERC4337Utils._buildDomainSeparator("Kernel", "0.2.2", address(kernel)), hash)); bytes memory sig = getWrongSignature(hash); assertEq(kernel.isValidSignature(hash, sig), bytes4(0xffffffff)); } From eacd7ed0cbe019f4986e1457983558b0ef291189 Mon Sep 17 00:00:00 2001 From: David Eiber Date: Thu, 9 Nov 2023 10:08:32 -0500 Subject: [PATCH 2/3] Update kernel version to 0.2.3 --- src/common/Constants.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/Constants.sol b/src/common/Constants.sol index e65d4328..e85dc7f3 100644 --- a/src/common/Constants.sol +++ b/src/common/Constants.sol @@ -4,7 +4,7 @@ import {ValidationData} from "./Types.sol"; // constants for kernel metadata string constant KERNEL_NAME = "Kernel"; -string constant KERNEL_VERSION = "0.2.2"; +string constant KERNEL_VERSION = "0.2.3"; // ERC4337 constants uint256 constant SIG_VALIDATION_FAILED_UINT = 1; From bb5d209ba3d8670b7d7e8ddcbd8206b7dd4a453c Mon Sep 17 00:00:00 2001 From: David Eiber Date: Thu, 9 Nov 2023 10:29:09 -0500 Subject: [PATCH 3/3] use kernel name and version from constants in tests --- test/foundry/KernelTestBase.sol | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/foundry/KernelTestBase.sol b/test/foundry/KernelTestBase.sol index b7ccce4b..7ea675d7 100644 --- a/test/foundry/KernelTestBase.sol +++ b/test/foundry/KernelTestBase.sol @@ -14,6 +14,7 @@ import {IKernelValidator} from "src/interfaces/IKernelValidator.sol"; import {Call, ExecutionDetail} from "src/common/Structs.sol"; import {ValidationData, ValidUntil, ValidAfter} from "src/common/Types.sol"; +import {KERNEL_VERSION, KERNEL_NAME} from "src/common/Constants.sol"; import {ERC4337Utils} from "test/foundry/utils/ERC4337Utils.sol"; import {Test} from "forge-std/Test.sol"; @@ -143,8 +144,8 @@ abstract contract KernelTestBase is Test { (bytes1 fields, string memory name, string memory version,, address verifyingContract, bytes32 salt,) = kernel.eip712Domain(); assertEq(fields, bytes1(hex"0f")); - assertEq(name, "Kernel"); - assertEq(version, "0.2.2"); + assertEq(name, KERNEL_NAME); + assertEq(version, KERNEL_VERSION); assertEq(verifyingContract, address(kernel)); assertEq(salt, bytes32(0)); } @@ -179,7 +180,7 @@ abstract contract KernelTestBase is Test { function test_validate_signature() external { Kernel kernel2 = Kernel(payable(factory.createAccount(address(kernelImpl), getInitializeData(), 3))); bytes32 hash = keccak256(abi.encodePacked("hello world")); - bytes32 digest = keccak256(abi.encodePacked("\x19\x01", ERC4337Utils._buildDomainSeparator("Kernel", "0.2.2", address(kernel)), hash)); + bytes32 digest = keccak256(abi.encodePacked("\x19\x01", ERC4337Utils._buildDomainSeparator(KERNEL_NAME, KERNEL_VERSION, address(kernel)), hash)); bytes memory sig = signHash(digest); assertEq(kernel.isValidSignature(hash, sig), Kernel.isValidSignature.selector); assertEq(kernel2.isValidSignature(hash, sig), bytes4(0xffffffff)); @@ -187,7 +188,7 @@ abstract contract KernelTestBase is Test { function test_fail_validate_wrongsignature() external { bytes32 hash = keccak256(abi.encodePacked("hello world")); - bytes32 digest = keccak256(abi.encodePacked("\x19\x01", ERC4337Utils._buildDomainSeparator("Kernel", "0.2.2", address(kernel)), hash)); + bytes32 digest = keccak256(abi.encodePacked("\x19\x01", ERC4337Utils._buildDomainSeparator(KERNEL_NAME, KERNEL_VERSION, address(kernel)), hash)); bytes memory sig = getWrongSignature(hash); assertEq(kernel.isValidSignature(hash, sig), bytes4(0xffffffff)); } @@ -475,7 +476,7 @@ abstract contract KernelTestBase is Test { return keccak256( abi.encodePacked( "\x19\x01", - ERC4337Utils._buildDomainSeparator("Kernel", "0.2.2", address(kernel)), + ERC4337Utils._buildDomainSeparator(KERNEL_NAME, KERNEL_VERSION, address(kernel)), ERC4337Utils.getStructHash(sig, validUntil, validAfter, validator, executor, enableData) ) );