Skip to content

Commit d191610

Browse files
authored
Feat/v3.1 rc3 (#118)
* feat: increase nonce on installModule when validator has been installed previously * rc3 * fmt
1 parent 51e935d commit d191610

File tree

2 files changed

+102
-6
lines changed

2 files changed

+102
-6
lines changed

src/Kernel.sol

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
5454
error InvalidModuleType();
5555
error InvalidCaller();
5656
error InvalidSelector();
57+
error InitConfigError(uint256 idx);
5758

5859
event Received(address sender, uint256 amount);
5960
event Upgraded(address indexed implementation);
@@ -92,9 +93,13 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
9293
}
9394
}
9495

95-
function initialize(ValidationId _rootValidator, IHook hook, bytes calldata validatorData, bytes calldata hookData)
96-
external
97-
{
96+
function initialize(
97+
ValidationId _rootValidator,
98+
IHook hook,
99+
bytes calldata validatorData,
100+
bytes calldata hookData,
101+
bytes[] calldata initConfig
102+
) external {
98103
ValidationStorage storage vs = _validationStorage();
99104
require(ValidationId.unwrap(vs.rootValidator) == bytes21(0), "already initialized");
100105
if (ValidationId.unwrap(_rootValidator) == bytes21(0)) {
@@ -108,6 +113,12 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
108113
ValidationConfig memory config = ValidationConfig({nonce: uint32(1), hook: hook});
109114
vs.currentNonce = 1;
110115
_installValidation(_rootValidator, config, validatorData, hookData);
116+
for (uint256 i = 0; i < initConfig.length; i++) {
117+
(bool success,) = address(this).call(initConfig[i]);
118+
if (!success) {
119+
revert InitConfigError(i);
120+
}
121+
}
111122
}
112123

113124
function changeRootValidator(
@@ -340,6 +351,12 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
340351
if (moduleType == MODULE_TYPE_VALIDATOR) {
341352
ValidationStorage storage vs = _validationStorage();
342353
ValidationId vId = ValidatorLib.validatorToIdentifier(IValidator(module));
354+
if (vs.validationConfig[vId].nonce == vs.currentNonce) {
355+
// only increase currentNonce when vId's currentNonce is same
356+
unchecked {
357+
vs.currentNonce++;
358+
}
359+
}
343360
ValidationConfig memory config =
344361
ValidationConfig({nonce: vs.currentNonce, hook: IHook(address(bytes20(initData[0:20])))});
345362
bytes calldata validatorData;
@@ -354,8 +371,10 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
354371
selectorData.length := calldataload(sub(selectorData.offset, 32))
355372
}
356373
_installValidation(vId, config, validatorData, hookData);
357-
// 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
358-
_setSelector(vId, bytes4(selectorData[0:4]), true);
374+
if (selectorData.length == 4) {
375+
// 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
376+
_setSelector(vId, bytes4(selectorData[0:4]), true);
377+
}
359378
} else if (moduleType == MODULE_TYPE_EXECUTOR) {
360379
bytes calldata executorData;
361380
bytes calldata hookData;

src/sdk/KernelTestBase.sol

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ abstract contract KernelTestBase is Test {
4444
FactoryStaker staker;
4545
IEntryPoint entrypoint;
4646
ValidationId rootValidation;
47+
bytes[] initConfig;
4748

4849
struct RootValidationConfig {
4950
IHook hook;
@@ -334,6 +335,24 @@ abstract contract KernelTestBase is Test {
334335
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
335336
}
336337

338+
function testInitConfig() external {
339+
bytes[] memory configs = new bytes[](1);
340+
MockValidator mv = new MockValidator();
341+
configs[0] = abi.encodeWithSelector(
342+
Kernel.installModule.selector, 1, address(mv), abi.encodePacked(address(0), abi.encode(hex"", hex"", hex""))
343+
);
344+
initConfig = configs;
345+
kernel = Kernel(payable(factory.getAddress(initData(), bytes32(0))));
346+
address deployed = factory.createAccount(initData(), bytes32(0));
347+
assertEq(deployed, address(kernel));
348+
assertEq(kernel.currentNonce(), 1);
349+
assertEq(ValidationId.unwrap(kernel.rootValidator()), ValidationId.unwrap(rootValidation));
350+
ValidationManager.ValidationConfig memory config =
351+
kernel.validationConfig(ValidatorLib.validatorToIdentifier(mv));
352+
assertEq(config.nonce, 1);
353+
assertEq(address(config.hook), address(1));
354+
}
355+
337356
function test_receive() external whenInitialized {
338357
vm.expectEmit(false, false, false, true, address(kernel));
339358
emit Kernel.Received(address(this), 1);
@@ -359,7 +378,8 @@ abstract contract KernelTestBase is Test {
359378
rootValidation,
360379
rootValidationConfig.hook,
361380
rootValidationConfig.validatorData,
362-
rootValidationConfig.hookData
381+
rootValidationConfig.hookData,
382+
initConfig
363383
);
364384
}
365385

@@ -654,6 +674,63 @@ abstract contract KernelTestBase is Test {
654674
WithHook
655675
}
656676

677+
function _installValidator(IValidator validator) internal {
678+
vm.deal(address(kernel), 1e18);
679+
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
680+
ops[0] = _prepareUserOp(
681+
VALIDATION_TYPE_ROOT,
682+
false,
683+
false,
684+
abi.encodeWithSelector(
685+
kernel.installModule.selector,
686+
1,
687+
address(validator),
688+
abi.encodePacked(
689+
address(0), // Hook
690+
abi.encode(
691+
hex"", // validator data
692+
hex"", // hook data
693+
hex"" // selector data
694+
)
695+
)
696+
),
697+
true,
698+
true
699+
);
700+
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
701+
}
702+
703+
function _uninstallValidator(IValidator validator) internal {
704+
vm.deal(address(kernel), 1e18);
705+
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
706+
ops[0] = _prepareUserOp(
707+
VALIDATION_TYPE_ROOT,
708+
false,
709+
false,
710+
abi.encodeWithSelector(kernel.uninstallModule.selector, 1, address(validator), hex""),
711+
true,
712+
true
713+
);
714+
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
715+
}
716+
717+
function testValidatorInstall() external whenInitialized {
718+
MockValidator mv = new MockValidator();
719+
_installValidator(mv);
720+
ValidationManager.ValidationConfig memory config =
721+
kernel.validationConfig(ValidatorLib.validatorToIdentifier(mv));
722+
assertEq(config.nonce, 1);
723+
assertEq(address(config.hook), address(1));
724+
_uninstallValidator(mv);
725+
config = kernel.validationConfig(ValidatorLib.validatorToIdentifier(mv));
726+
assertEq(config.nonce, 1);
727+
assertEq(address(config.hook), address(0));
728+
_installValidator(mv);
729+
config = kernel.validationConfig(ValidatorLib.validatorToIdentifier(mv));
730+
assertEq(config.nonce, 2);
731+
assertEq(address(config.hook), address(1));
732+
}
733+
657734
function _installAction(HookInfo withHook) internal {
658735
vm.deal(address(kernel), 1e18);
659736
MockAction mockAction = new MockAction();

0 commit comments

Comments
 (0)