forked from zerodevapp/kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathERC165SessionKeyValidator.sol
More file actions
68 lines (58 loc) · 2.75 KB
/
ERC165SessionKeyValidator.sol
File metadata and controls
68 lines (58 loc) · 2.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {UserOperation} from "I4337/interfaces/UserOperation.sol";
import {ECDSA} from "solady/utils/ECDSA.sol";
import {IKernelValidator} from "../interfaces/IKernelValidator.sol";
import {ValidAfter, ValidUntil, ValidationData, packValidationData} from "../common/Types.sol";
import {SIG_VALIDATION_FAILED} from "../common/Constants.sol";
// idea, we can make this merkle root
struct ERC165SessionKeyStorage {
bool enabled;
bytes4 selector;
bytes4 interfaceId;
ValidAfter validAfter;
ValidUntil validUntil;
uint32 addressOffset;
}
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
contract ERC165SessionKeyValidator is IKernelValidator {
mapping(address sessionKey => mapping(address kernel => ERC165SessionKeyStorage)) public sessionKeys;
function enable(bytes calldata _data) external payable {
address sessionKey = address(bytes20(_data[0:20]));
bytes4 interfaceId = bytes4(_data[20:24]);
bytes4 selector = bytes4(_data[24:28]);
ValidAfter validAfter = ValidAfter.wrap(uint48(bytes6(_data[28:34])));
ValidUntil validUntil = ValidUntil.wrap(uint48(bytes6(_data[34:40])));
uint32 addressOffset = uint32(bytes4(_data[40:44]));
sessionKeys[sessionKey][msg.sender] =
ERC165SessionKeyStorage(true, selector, interfaceId, validAfter, validUntil, addressOffset);
}
function disable(bytes calldata _data) external payable {
address sessionKey = address(bytes20(_data[0:20]));
delete sessionKeys[sessionKey][msg.sender];
}
function validateSignature(bytes32, bytes calldata) external pure override returns (ValidationData) {
revert NotImplemented();
}
function validateUserOp(UserOperation calldata _userOp, bytes32 _userOpHash, uint256)
external
payable
returns (ValidationData)
{
bytes32 hash = ECDSA.toEthSignedMessageHash(_userOpHash);
address recovered = ECDSA.recover(hash, _userOp.signature);
ERC165SessionKeyStorage storage sessionKey = sessionKeys[recovered][_userOp.sender];
if (!sessionKey.enabled) {
return SIG_VALIDATION_FAILED;
}
require(bytes4(_userOp.callData[0:4]) == sessionKey.selector, "not supported selector");
address token = address(bytes20(_userOp.callData[sessionKey.addressOffset:sessionKey.addressOffset + 20]));
require(IERC165(token).supportsInterface(sessionKey.interfaceId), "does not support interface");
return packValidationData(sessionKey.validAfter, sessionKey.validUntil);
}
function validCaller(address, bytes calldata) external pure override returns (bool) {
revert NotImplemented();
}
}