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
22 changes: 16 additions & 6 deletions src/validator/SessionKeyOwnedValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,15 @@ contract SessionKeyOwnedValidator is IKernelValidator {
override
returns (ValidationData validationData)
{
bytes32 hash = ECDSA.toEthSignedMessageHash(_userOpHash);
address recovered = ECDSA.recover(hash, _userOp.signature);

address recovered = ECDSA.recover(_userOpHash, _userOp.signature);
SessionKeyStorage storage sessionKey = sessionKeyStorage[recovered][msg.sender];
if (ValidUntil.unwrap(sessionKey.validUntil) != 0) {
return packValidationData(sessionKey.validAfter, sessionKey.validUntil);
}

bytes32 hash = ECDSA.toEthSignedMessageHash(_userOpHash);
recovered = ECDSA.recover(hash, _userOp.signature);
sessionKey = sessionKeyStorage[recovered][msg.sender];
if (ValidUntil.unwrap(sessionKey.validUntil) == 0) {
// we do not allow validUntil == 0 here
return SIG_VALIDATION_FAILED;
Expand All @@ -52,10 +57,15 @@ contract SessionKeyOwnedValidator is IKernelValidator {
}

function validateSignature(bytes32 hash, bytes calldata signature) public view override returns (ValidationData) {
bytes32 ethhash = ECDSA.toEthSignedMessageHash(hash);
address recovered = ECDSA.recover(ethhash, signature);

address recovered = ECDSA.recover(hash, signature);
SessionKeyStorage storage sessionKey = sessionKeyStorage[recovered][msg.sender];
if (ValidUntil.unwrap(sessionKey.validUntil) != 0) {
return packValidationData(sessionKey.validAfter, sessionKey.validUntil);
}

bytes32 ethhash = ECDSA.toEthSignedMessageHash(hash);
recovered = ECDSA.recover(ethhash, signature);
sessionKey = sessionKeyStorage[recovered][msg.sender];
if (ValidUntil.unwrap(sessionKey.validUntil) == 0) {
// we do not allow validUntil == 0 here
return SIG_VALIDATION_FAILED;
Expand Down
87 changes: 87 additions & 0 deletions test/foundry/validator/SessionKeyOwnedValidator.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "src/factory/AdminLessERC1967Factory.sol";
import "src/Kernel.sol";
import "src/validator/ECDSAValidator.sol";
import "src/factory/KernelFactory.sol";
// test artifacts
import "src/test/TestValidator.sol";
import "src/test/TestExecutor.sol";
import "src/test/TestERC721.sol";
import "src/test/TestERC20.sol";
// test utils
import "forge-std/Test.sol";
import "test/foundry/utils/ERC4337Utils.sol";
// test actions/validators
import "src/validator/SessionKeyOwnedValidator.sol";

using ERC4337Utils for EntryPoint;

contract SessionKeyOwnedValidatorTest is KernelTestBase {
SessionKeyOwnedValidator sessionKeyValidator;
TestERC20 testToken;
address sessionKey;
uint256 sessionKeyPriv;

uint48 validAfter = uint48(0);
uint48 validUntil = type(uint48).max;

function setUp() public {
_initialize();
defaultValidator = new ECDSAValidator();
sessionKeyValidator = new SessionKeyOwnedValidator();
_setAddress();
(sessionKey, sessionKeyPriv) = makeAddrAndKey("sessionKey");
testToken = new TestERC20();
}

function test_mode_2_no_paymaster() external {
testToken.mint(address(kernel), 100e18);
UserOperation memory op = entryPoint.fillUserOp(
address(kernel),
abi.encodeWithSelector(
Kernel.execute.selector,
address(testToken),
0,
abi.encodeWithSelector(ERC20.transfer.selector, beneficiary, 100),
Operation.Call
)
);

bytes memory enableData = abi.encodePacked(sessionKey, validAfter, validUntil);

bytes32 digest = getTypedDataHash(
address(kernel),
Kernel.execute.selector,
validAfter,
validUntil,
address(sessionKeyValidator),
address(0),
enableData
);

(uint8 v, bytes32 r, bytes32 s) = vm.sign(ownerKey, digest);

op.signature = abi.encodePacked(
bytes4(0x00000002),
validAfter,
validUntil,
address(sessionKeyValidator),
address(0),
uint256(enableData.length),
enableData,
uint256(65),
r,
s,
v,
entryPoint.signUserOpHash(vm, sessionKeyPriv, op)
);

UserOperation[] memory ops = new UserOperation[](1);
ops[0] = op;
logGas(op);

entryPoint.handleOps(ops, beneficiary);
}
}