Skip to content

Commit 55ad69d

Browse files
authored
feat: add default hook, now only support msg.sender == entrypoint as default (#110)
* v3.1-beta * fmt
1 parent 256f1f4 commit 55ad69d

File tree

3 files changed

+100
-32
lines changed

3 files changed

+100
-32
lines changed

src/Kernel.sol

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
119119

120120
function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) {
121121
name = "Kernel";
122-
version = "0.3.0-beta";
122+
version = "0.3.1-beta";
123123
}
124124

125125
receive() external payable {
@@ -151,8 +151,16 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
151151
} else {
152152
// action installed
153153
bytes memory context;
154-
if (address(config.hook) != address(1)) {
154+
if (
155+
address(config.hook) != address(1) && address(config.hook) != 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF
156+
) {
155157
context = _doPreHook(config.hook, msg.value, msg.data);
158+
} else if (address(config.hook) == 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF) {
159+
// for selector manager, address(0) for the hook will default to type(address).max,
160+
// and this will only allow entrypoints to interact
161+
if (msg.sender != address(entrypoint)) {
162+
revert InvalidCaller();
163+
}
156164
}
157165
// execute action
158166
if (config.callType == CALLTYPE_SINGLE) {
@@ -312,14 +320,18 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
312320
ValidationConfig({nonce: vs.currentNonce, hook: IHook(address(bytes20(initData[0:20])))});
313321
bytes calldata validatorData;
314322
bytes calldata hookData;
323+
bytes calldata selectorData;
315324
assembly {
316325
validatorData.offset := add(add(initData.offset, 52), calldataload(add(initData.offset, 20)))
317326
validatorData.length := calldataload(sub(validatorData.offset, 32))
318327
hookData.offset := add(add(initData.offset, 52), calldataload(add(initData.offset, 52)))
319328
hookData.length := calldataload(sub(hookData.offset, 32))
329+
selectorData.offset := add(add(initData.offset, 52), calldataload(add(initData.offset, 84)))
330+
selectorData.length := calldataload(sub(selectorData.offset, 32))
320331
}
321332
_installValidation(vId, config, validatorData, hookData);
322-
//_installHook(config.hook, hookData); hook install is handled inside installvalidation
333+
// NOTE: we don't allow configure on selector data on v3.1, but using bytes instead of bytes4 for selector data to make sure we are future proof
334+
_setSelector(vId, bytes4(selectorData[0:4]), true);
323335
} else if (moduleType == MODULE_TYPE_EXECUTOR) {
324336
bytes calldata executorData;
325337
bytes calldata hookData;
@@ -470,7 +482,7 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
470482
}
471483

472484
function accountId() external pure override returns (string memory accountImplementationId) {
473-
return "kernel.advanced.v0.3.0-beta";
485+
return "kernel.advanced.v0.3.1";
474486
}
475487

476488
function supportsExecutionMode(ExecMode mode) external pure override returns (bool) {

src/core/SelectorManager.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ abstract contract SelectorManager {
3737

3838
function _installSelector(bytes4 selector, address target, IHook hook, bytes calldata selectorData) internal {
3939
if (address(hook) == address(0)) {
40-
hook = IHook(address(1));
40+
hook = IHook(address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF));
4141
}
4242
SelectorConfig storage ss = _selectorConfig(selector);
4343
// we are going to install only through call/delegatecall

src/sdk/KernelTestBase.sol

Lines changed: 83 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ abstract contract KernelTestBase is Test {
190190
);
191191

192192
bytes32 digest = keccak256(
193-
abi.encodePacked("\x19\x01", _buildDomainSeparator("Kernel", "0.3.0-beta", address(kernel)), hash)
193+
abi.encodePacked("\x19\x01", _buildDomainSeparator("Kernel", "0.3.1-beta", address(kernel)), hash)
194194
);
195195

196196
return digest;
@@ -638,7 +638,13 @@ abstract contract KernelTestBase is Test {
638638
return abi.encode(permissions);
639639
}
640640

641-
function _installAction(bool withHook) internal {
641+
enum HookInfo {
642+
NoHook,
643+
DefaultHook,
644+
WithHook
645+
}
646+
647+
function _installAction(HookInfo withHook) internal {
642648
vm.deal(address(kernel), 1e18);
643649
MockAction mockAction = new MockAction();
644650
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
@@ -652,8 +658,10 @@ abstract contract KernelTestBase is Test {
652658
address(mockAction),
653659
abi.encodePacked(
654660
MockAction.doSomething.selector,
655-
withHook ? address(mockHook) : address(0),
656-
withHook
661+
withHook == HookInfo.WithHook
662+
? address(mockHook)
663+
: withHook == HookInfo.NoHook ? address(1) : address(0),
664+
withHook == HookInfo.WithHook
657665
? abi.encode(hex"ff", abi.encodePacked(bytes1(0xff), "hookData"))
658666
: abi.encode(hex"ff", hex"")
659667
)
@@ -664,14 +672,33 @@ abstract contract KernelTestBase is Test {
664672
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
665673
}
666674

667-
function testActionInstall(bool withHook) external whenInitialized {
675+
function testActionInstall(uint8 hookUint) external whenInitialized {
676+
vm.assume(uint8(hookUint) < 3);
677+
HookInfo withHook = HookInfo(hookUint);
668678
_installAction(withHook);
669679
SelectorManager.SelectorConfig memory config = kernel.selectorConfig(MockAction.doSomething.selector);
670-
assertEq(address(config.hook), withHook ? address(mockHook) : address(1));
671-
vm.expectEmit(address(kernel));
672-
emit MockAction.MockActionEvent(address(kernel));
673-
MockAction(address(kernel)).doSomething();
674-
if (withHook) {
680+
assertEq(
681+
address(config.hook),
682+
withHook == HookInfo.WithHook
683+
? address(mockHook)
684+
: withHook == HookInfo.NoHook ? address(1) : address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF)
685+
);
686+
if (withHook != HookInfo.DefaultHook) {
687+
vm.expectEmit(address(kernel));
688+
emit MockAction.MockActionEvent(address(kernel));
689+
MockAction(address(kernel)).doSomething();
690+
} else {
691+
vm.expectRevert();
692+
MockAction(address(kernel)).doSomething();
693+
PackedUserOperation memory op = _prepareUserOp(
694+
VALIDATION_TYPE_ROOT, false, false, abi.encodeWithSelector(MockAction.doSomething.selector), true, true
695+
);
696+
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
697+
ops[0] = op;
698+
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
699+
}
700+
701+
if (withHook == HookInfo.WithHook) {
675702
assertEq(mockHook.data(address(kernel)), abi.encodePacked("hookData"));
676703
assertEq(
677704
mockHook.preHookData(address(kernel)), abi.encodePacked(address(this), MockAction.doSomething.selector)
@@ -680,7 +707,9 @@ abstract contract KernelTestBase is Test {
680707
}
681708
}
682709

683-
function testActionUninstall(bool withHook) external whenInitialized {
710+
function testActionUninstall(uint8 hookUint) external whenInitialized {
711+
vm.assume(uint8(hookUint) < 3);
712+
HookInfo withHook = HookInfo(hookUint);
684713
_installAction(withHook);
685714
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
686715
ops[0] = _prepareUserOp(
@@ -703,7 +732,7 @@ abstract contract KernelTestBase is Test {
703732
assertEq(address(config.target), address(0));
704733
}
705734

706-
function _installFallback(bool withHook) internal {
735+
function _installFallback(HookInfo withHook) internal {
707736
vm.deal(address(kernel), 1e18);
708737
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
709738
ops[0] = _prepareUserOp(
@@ -716,8 +745,10 @@ abstract contract KernelTestBase is Test {
716745
address(mockFallback),
717746
abi.encodePacked(
718747
MockFallback.fallbackFunction.selector,
719-
withHook ? address(mockHook) : address(0),
720-
withHook
748+
withHook == HookInfo.WithHook
749+
? address(mockHook)
750+
: withHook == HookInfo.NoHook ? address(1) : address(0),
751+
withHook == HookInfo.WithHook
721752
? abi.encode(abi.encodePacked(hex"00", "fallbackData"), abi.encodePacked(bytes1(0xff), "hookData"))
722753
: abi.encode(abi.encodePacked(hex"00", "fallbackData"), abi.encodePacked(""))
723754
)
@@ -728,20 +759,43 @@ abstract contract KernelTestBase is Test {
728759
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
729760
}
730761

731-
function testFallbackInstall(bool withHook) external whenInitialized {
762+
function testFallbackInstall(uint8 hookUint) external whenInitialized {
763+
vm.assume(uint8(hookUint) < 3);
764+
HookInfo withHook = HookInfo(hookUint);
732765
_installFallback(withHook);
733766
assertEq(mockFallback.data(address(kernel)), abi.encodePacked("fallbackData"));
734767

735768
SelectorManager.SelectorConfig memory config = kernel.selectorConfig(MockFallback.fallbackFunction.selector);
736-
assertEq(address(config.hook), withHook ? address(mockHook) : address(1));
769+
assertEq(
770+
address(config.hook),
771+
withHook == HookInfo.WithHook
772+
? address(mockHook)
773+
: withHook == HookInfo.NoHook ? address(1) : address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF)
774+
);
737775
assertEq(address(config.target), address(mockFallback));
738-
739-
(bool success, bytes memory result) =
740-
address(kernel).call(abi.encodeWithSelector(MockFallback.fallbackFunction.selector, uint256(10)));
741-
assertTrue(success);
742-
(uint256 res) = abi.decode(result, (uint256));
743-
assertEq(res, 100);
744-
if (withHook) {
776+
if (withHook != HookInfo.DefaultHook) {
777+
(bool success, bytes memory result) =
778+
address(kernel).call(abi.encodeWithSelector(MockFallback.fallbackFunction.selector, uint256(10)));
779+
assertTrue(success);
780+
(uint256 res) = abi.decode(result, (uint256));
781+
assertEq(res, 100);
782+
} else {
783+
(bool success, bytes memory result) =
784+
address(kernel).call(abi.encodeWithSelector(MockFallback.fallbackFunction.selector, uint256(10)));
785+
assertFalse(success);
786+
PackedUserOperation memory op = _prepareUserOp(
787+
VALIDATION_TYPE_ROOT,
788+
false,
789+
false,
790+
abi.encodeWithSelector(MockFallback.fallbackFunction.selector, uint256(10)),
791+
true,
792+
true
793+
);
794+
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
795+
ops[0] = op;
796+
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
797+
}
798+
if (withHook == HookInfo.WithHook) {
745799
assertEq(mockHook.data(address(kernel)), abi.encodePacked("hookData"));
746800
assertEq(
747801
mockHook.preHookData(address(kernel)),
@@ -751,7 +805,9 @@ abstract contract KernelTestBase is Test {
751805
}
752806
}
753807

754-
function testFallbackUninstall(bool withHook) external whenInitialized {
808+
function testFallbackUninstall(uint8 hookUint) external whenInitialized {
809+
vm.assume(uint8(hookUint) < 3);
810+
HookInfo withHook = HookInfo(hookUint);
755811
_installFallback(withHook);
756812
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
757813
ops[0] = _prepareUserOp(
@@ -840,7 +896,7 @@ abstract contract KernelTestBase is Test {
840896
function testSignatureRoot(bytes32 hash) external whenInitialized {
841897
bytes32 wrappedHash = keccak256(abi.encode(keccak256("Kernel(bytes32 hash)"), hash));
842898
bytes32 digest = keccak256(
843-
abi.encodePacked("\x19\x01", _buildDomainSeparator("Kernel", "0.3.0-beta", address(kernel)), wrappedHash)
899+
abi.encodePacked("\x19\x01", _buildDomainSeparator("Kernel", "0.3.1-beta", address(kernel)), wrappedHash)
844900
);
845901
bytes memory sig = _rootSignDigest(digest, true);
846902
sig = abi.encodePacked(hex"00", sig);
@@ -868,7 +924,7 @@ abstract contract KernelTestBase is Test {
868924

869925
bytes32 wrappedHash = keccak256(abi.encode(keccak256("Kernel(bytes32 hash)"), hash));
870926
bytes32 digest = keccak256(
871-
abi.encodePacked("\x19\x01", _buildDomainSeparator("Kernel", "0.3.0-beta", address(kernel)), wrappedHash)
927+
abi.encodePacked("\x19\x01", _buildDomainSeparator("Kernel", "0.3.1-beta", address(kernel)), wrappedHash)
872928
);
873929
bytes memory sig = _validatorSignDigest(digest, true);
874930
sig = abi.encodePacked(hex"01", address(enabledValidator), sig);
@@ -895,7 +951,7 @@ abstract contract KernelTestBase is Test {
895951
);
896952
bytes32 wrappedHash = keccak256(abi.encode(keccak256("Kernel(bytes32 hash)"), hash));
897953
bytes32 digest = keccak256(
898-
abi.encodePacked("\x19\x01", _buildDomainSeparator("Kernel", "0.3.0-beta", address(kernel)), wrappedHash)
954+
abi.encodePacked("\x19\x01", _buildDomainSeparator("Kernel", "0.3.1-beta", address(kernel)), wrappedHash)
899955
);
900956
bytes memory sig = _permissionSignDigest(digest, true);
901957
sig = abi.encodePacked(hex"02", PermissionId.unwrap(enabledPermission), hex"ff", sig);

0 commit comments

Comments
 (0)