Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions src/Kernel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/common/Constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 9 additions & 4 deletions test/foundry/KernelTestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -177,13 +178,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_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));
}

function test_fail_validate_wrongsignature() external {
bytes32 hash = keccak256(abi.encodePacked("hello world"));
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));
}
Expand Down Expand Up @@ -471,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)
)
);
Expand Down