Skip to content

Commit

Permalink
Feat/v3.1 rc3 (#118)
Browse files Browse the repository at this point in the history
* feat: increase nonce on installModule when validator has been installed previously

* rc3

* fmt
  • Loading branch information
leekt authored Jun 3, 2024
1 parent 51e935d commit d191610
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 6 deletions.
29 changes: 24 additions & 5 deletions src/Kernel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
error InvalidModuleType();
error InvalidCaller();
error InvalidSelector();
error InitConfigError(uint256 idx);

event Received(address sender, uint256 amount);
event Upgraded(address indexed implementation);
Expand Down Expand Up @@ -92,9 +93,13 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
}
}

function initialize(ValidationId _rootValidator, IHook hook, bytes calldata validatorData, bytes calldata hookData)
external
{
function initialize(
ValidationId _rootValidator,
IHook hook,
bytes calldata validatorData,
bytes calldata hookData,
bytes[] calldata initConfig
) external {
ValidationStorage storage vs = _validationStorage();
require(ValidationId.unwrap(vs.rootValidator) == bytes21(0), "already initialized");
if (ValidationId.unwrap(_rootValidator) == bytes21(0)) {
Expand All @@ -108,6 +113,12 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
ValidationConfig memory config = ValidationConfig({nonce: uint32(1), hook: hook});
vs.currentNonce = 1;
_installValidation(_rootValidator, config, validatorData, hookData);
for (uint256 i = 0; i < initConfig.length; i++) {
(bool success,) = address(this).call(initConfig[i]);
if (!success) {
revert InitConfigError(i);
}
}
}

function changeRootValidator(
Expand Down Expand Up @@ -340,6 +351,12 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
if (moduleType == MODULE_TYPE_VALIDATOR) {
ValidationStorage storage vs = _validationStorage();
ValidationId vId = ValidatorLib.validatorToIdentifier(IValidator(module));
if (vs.validationConfig[vId].nonce == vs.currentNonce) {
// only increase currentNonce when vId's currentNonce is same
unchecked {
vs.currentNonce++;
}
}
ValidationConfig memory config =
ValidationConfig({nonce: vs.currentNonce, hook: IHook(address(bytes20(initData[0:20])))});
bytes calldata validatorData;
Expand All @@ -354,8 +371,10 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
selectorData.length := calldataload(sub(selectorData.offset, 32))
}
_installValidation(vId, config, validatorData, hookData);
// 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
_setSelector(vId, bytes4(selectorData[0:4]), true);
if (selectorData.length == 4) {
// 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
_setSelector(vId, bytes4(selectorData[0:4]), true);
}
} else if (moduleType == MODULE_TYPE_EXECUTOR) {
bytes calldata executorData;
bytes calldata hookData;
Expand Down
79 changes: 78 additions & 1 deletion src/sdk/KernelTestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ abstract contract KernelTestBase is Test {
FactoryStaker staker;
IEntryPoint entrypoint;
ValidationId rootValidation;
bytes[] initConfig;

struct RootValidationConfig {
IHook hook;
Expand Down Expand Up @@ -334,6 +335,24 @@ abstract contract KernelTestBase is Test {
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
}

function testInitConfig() external {
bytes[] memory configs = new bytes[](1);
MockValidator mv = new MockValidator();
configs[0] = abi.encodeWithSelector(
Kernel.installModule.selector, 1, address(mv), abi.encodePacked(address(0), abi.encode(hex"", hex"", hex""))
);
initConfig = configs;
kernel = Kernel(payable(factory.getAddress(initData(), bytes32(0))));
address deployed = factory.createAccount(initData(), bytes32(0));
assertEq(deployed, address(kernel));
assertEq(kernel.currentNonce(), 1);
assertEq(ValidationId.unwrap(kernel.rootValidator()), ValidationId.unwrap(rootValidation));
ValidationManager.ValidationConfig memory config =
kernel.validationConfig(ValidatorLib.validatorToIdentifier(mv));
assertEq(config.nonce, 1);
assertEq(address(config.hook), address(1));
}

function test_receive() external whenInitialized {
vm.expectEmit(false, false, false, true, address(kernel));
emit Kernel.Received(address(this), 1);
Expand All @@ -359,7 +378,8 @@ abstract contract KernelTestBase is Test {
rootValidation,
rootValidationConfig.hook,
rootValidationConfig.validatorData,
rootValidationConfig.hookData
rootValidationConfig.hookData,
initConfig
);
}

Expand Down Expand Up @@ -654,6 +674,63 @@ abstract contract KernelTestBase is Test {
WithHook
}

function _installValidator(IValidator validator) internal {
vm.deal(address(kernel), 1e18);
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
ops[0] = _prepareUserOp(
VALIDATION_TYPE_ROOT,
false,
false,
abi.encodeWithSelector(
kernel.installModule.selector,
1,
address(validator),
abi.encodePacked(
address(0), // Hook
abi.encode(
hex"", // validator data
hex"", // hook data
hex"" // selector data
)
)
),
true,
true
);
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
}

function _uninstallValidator(IValidator validator) internal {
vm.deal(address(kernel), 1e18);
PackedUserOperation[] memory ops = new PackedUserOperation[](1);
ops[0] = _prepareUserOp(
VALIDATION_TYPE_ROOT,
false,
false,
abi.encodeWithSelector(kernel.uninstallModule.selector, 1, address(validator), hex""),
true,
true
);
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
}

function testValidatorInstall() external whenInitialized {
MockValidator mv = new MockValidator();
_installValidator(mv);
ValidationManager.ValidationConfig memory config =
kernel.validationConfig(ValidatorLib.validatorToIdentifier(mv));
assertEq(config.nonce, 1);
assertEq(address(config.hook), address(1));
_uninstallValidator(mv);
config = kernel.validationConfig(ValidatorLib.validatorToIdentifier(mv));
assertEq(config.nonce, 1);
assertEq(address(config.hook), address(0));
_installValidator(mv);
config = kernel.validationConfig(ValidatorLib.validatorToIdentifier(mv));
assertEq(config.nonce, 2);
assertEq(address(config.hook), address(1));
}

function _installAction(HookInfo withHook) internal {
vm.deal(address(kernel), 1e18);
MockAction mockAction = new MockAction();
Expand Down

0 comments on commit d191610

Please sign in to comment.