From 507a20a9a967c5c0e3acf6f4a1dc371a8e202c25 Mon Sep 17 00:00:00 2001 From: Colin Date: Tue, 26 Nov 2024 19:14:29 -0800 Subject: [PATCH 01/17] chore: clean up unused code R1 validation and keys were unreachable after changing the init interface, K1 validation was unused since it was validated directly without a module (simple signature instead of modular signature) Fallback modules were entirely unused. Modules and exec modules could have been used, but were not and weren't supported by the factory to be installed at init. --- src/AAFactory.sol | 6 +- src/SsoAccount.sol | 12 +-- src/auth/Auth.sol | 5 +- src/auth/ModuleAuth.sol | 20 ----- src/handlers/ValidationHandler.sol | 26 +------ src/interfaces/IModuleManager.sol | 42 ----------- src/interfaces/IOwnerManager.sol | 54 ------------- src/interfaces/ISsoAccount.sol | 8 +- src/interfaces/IValidatorManager.sol | 40 ---------- src/libraries/SsoStorage.sol | 16 ---- src/managers/ModuleManager.sol | 109 --------------------------- src/managers/OwnerManager.sol | 63 ---------------- src/managers/ValidatorManager.sol | 52 ------------- 13 files changed, 7 insertions(+), 446 deletions(-) delete mode 100644 src/auth/ModuleAuth.sol diff --git a/src/AAFactory.sol b/src/AAFactory.sol index 4eef51fd..7162e537 100644 --- a/src/AAFactory.sol +++ b/src/AAFactory.sol @@ -35,14 +35,12 @@ contract AAFactory is UpgradeableBeacon { /// @param _salt The salt used for the `create2` deployment to make the address deterministic. /// @param _uniqueAccountId A unique identifier for the new account. /// @param _initialValidators An array of initial validators for the new account. - /// @param _initialModules An array of initial modules to be added to the new account. /// @param _initialK1Owners An array of initial owners of the K1 key for the new account. /// @return accountAddress The address of the newly deployed SSO account. function deployProxySsoAccount( bytes32 _salt, string calldata _uniqueAccountId, bytes[] calldata _initialValidators, - bytes[] calldata _initialModules, address[] calldata _initialK1Owners ) external returns (address accountAddress) { require(accountMappings[_uniqueAccountId] == address(0), "Account already exists"); @@ -64,8 +62,8 @@ contract AAFactory is UpgradeableBeacon { require(success, "Deployment failed"); (accountAddress) = abi.decode(returnData, (address)); - // Initialize the newly deployed account with validators, modules, and K1 owners. - ISsoAccount(accountAddress).initialize(_initialValidators, _initialModules, _initialK1Owners); + // Initialize the newly deployed account with validators and K1 owners. + ISsoAccount(accountAddress).initialize(_initialValidators, _initialK1Owners); accountMappings[_uniqueAccountId] = accountAddress; diff --git a/src/SsoAccount.sol b/src/SsoAccount.sol index 42b87573..adbf2da4 100644 --- a/src/SsoAccount.sol +++ b/src/SsoAccount.sol @@ -50,22 +50,12 @@ contract SsoAccount is /// @dev Sets passkey and passkey validator within account storage /// @param _initialValidators An array of module validator addresses and initial validation keys /// in an ABI encoded format of `abi.encode(validatorAddr,validationKey))`. - /// @param _initialModules An array of native module addresses and their initialize data - /// in an ABI encoded format of `abi.encode(moduleAddr,initData))`. /// @param _initialK1Owners An array of addresses with full control over the account. - function initialize( - bytes[] calldata _initialValidators, - bytes[] calldata _initialModules, - address[] calldata _initialK1Owners - ) external initializer { + function initialize(bytes[] calldata _initialValidators, address[] calldata _initialK1Owners) external initializer { for (uint256 i = 0; i < _initialValidators.length; ++i) { (address validatorAddr, bytes memory validationKey) = abi.decode(_initialValidators[i], (address, bytes)); _addModuleValidator(validatorAddr, validationKey); } - for (uint256 i = 0; i < _initialModules.length; ++i) { - (address moduleAddr, bytes memory initData) = abi.decode(_initialModules[i], (address, bytes)); - _addNativeModule(moduleAddr, initData); - } for (uint256 i = 0; i < _initialK1Owners.length; ++i) { _k1AddOwner(_initialK1Owners[i]); } diff --git a/src/auth/Auth.sol b/src/auth/Auth.sol index dd68419b..1da7f83f 100644 --- a/src/auth/Auth.sol +++ b/src/auth/Auth.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.24; import { BootloaderAuth } from "./BootloaderAuth.sol"; -import { ModuleAuth } from "./ModuleAuth.sol"; import { SelfAuth } from "./SelfAuth.sol"; import { HookAuth } from "./HookAuth.sol"; import { Errors } from "../libraries/Errors.sol"; @@ -12,9 +11,9 @@ import { Errors } from "../libraries/Errors.sol"; * @notice Abstract contract that organizes authentication logic for the contract * @author https://getclave.io */ -abstract contract Auth is BootloaderAuth, SelfAuth, ModuleAuth, HookAuth { +abstract contract Auth is BootloaderAuth, SelfAuth, HookAuth { modifier onlySelfOrModule() { - if (msg.sender != address(this) && !_isModule(msg.sender)) { + if (msg.sender != address(this)) { revert Errors.NOT_FROM_SELF_OR_MODULE(); } _; diff --git a/src/auth/ModuleAuth.sol b/src/auth/ModuleAuth.sol deleted file mode 100644 index e0b2b697..00000000 --- a/src/auth/ModuleAuth.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.24; - -import { Errors } from "../libraries/Errors.sol"; - -/** - * @title ModuleAuth - * @notice Abstract contract that allows only calls from modules - * @author https://getclave.io - */ -abstract contract ModuleAuth { - function _isModule(address addr) internal view virtual returns (bool); - - modifier onlyModule() { - if (!_isModule(msg.sender)) { - revert Errors.NOT_FROM_MODULE(); - } - _; - } -} diff --git a/src/handlers/ValidationHandler.sol b/src/handlers/ValidationHandler.sol index 757bb6de..60168c54 100644 --- a/src/handlers/ValidationHandler.sol +++ b/src/handlers/ValidationHandler.sol @@ -20,31 +20,7 @@ abstract contract ValidationHandler is OwnerManager, ValidatorManager { bytes32 signedHash, bytes memory signature ) internal view returns (bool) { - if (_r1IsValidator(validator)) { - mapping(bytes => bytes) storage owners = OwnerManager._r1OwnersLinkedList(); - bytes memory cursor = owners[BytesLinkedList.SENTINEL_BYTES]; - while (cursor.length > BytesLinkedList.SENTINEL_LENGTH) { - bytes32[2] memory pubKey = abi.decode(cursor, (bytes32[2])); - - bool _success = IR1Validator(validator).validateSignature(signedHash, signature, pubKey); - - if (_success) { - return true; - } - - cursor = owners[cursor]; - } - } else if (_k1IsValidator(validator)) { - address recoveredAddress = IK1Validator(validator).validateSignature(signedHash, signature); - - if (recoveredAddress == address(0)) { - return false; - } - - if (OwnerManager._k1IsOwner(recoveredAddress)) { - return true; - } - } else if (_isModuleValidator(validator)) { + if (_isModuleValidator(validator)) { return IModuleValidator(validator).handleValidation(signedHash, signature); } diff --git a/src/interfaces/IModuleManager.sol b/src/interfaces/IModuleManager.sol index f78ba289..108acce7 100644 --- a/src/interfaces/IModuleManager.sol +++ b/src/interfaces/IModuleManager.sol @@ -6,51 +6,9 @@ pragma solidity ^0.8.24; * @author https://getclave.io */ interface IModuleManager { - /** - * @notice Event emitted when a module is added - * @param module address - Address of the added module - */ - event AddModule(address indexed module); - /** * @notice Event emitted when a module is removed * @param module address - Address of the removed module */ event RemoveModule(address indexed module); - - /** - * @notice Add a module to the list of modules and call it's init function - * @dev Can only be called by self or a module - * @param moduleAndData bytes calldata - Address of the module and data to initialize it with - */ - function addModule(bytes calldata moduleAndData) external; - - /** - * @notice Remove a module from the list of modules and call it's disable function - * @dev Can only be called by self or a module - * @param module address - Address of the module to remove - */ - function removeModule(address module) external; - - /** - * @notice Allow modules to execute arbitrary calls on behalf of the account - * @dev Can only be called by a module - * @param to address - Address to call - * @param value uint256 - Eth to send with call - * @param data bytes memory - Data to make the call with - */ - function executeFromModule(address to, uint256 value, bytes memory data) external; - - /** - * @notice Check if an address is in the list of modules - * @param addr address - Address to check - * @return bool - True if the address is a module, false otherwise - */ - function isModule(address addr) external returns (bool); - - /** - * @notice Get the list of modules - * @return moduleList address[] memory - List of modules - */ - function listModules() external view returns (address[] memory moduleList); } diff --git a/src/interfaces/IOwnerManager.sol b/src/interfaces/IOwnerManager.sol index 062ff2a5..4799fc02 100644 --- a/src/interfaces/IOwnerManager.sol +++ b/src/interfaces/IOwnerManager.sol @@ -6,43 +6,18 @@ pragma solidity ^0.8.24; * @author https://getclave.io */ interface IOwnerManager { - /** - * @notice Event emitted when a r1 owner is added - * @param pubKey bytes - r1 owner that has been added - */ - event R1AddOwner(bytes pubKey); - /** * @notice Event emitted when a k1 owner is added * @param addr address - k1 owner that has been added */ event K1AddOwner(address indexed addr); - /** - * @notice Event emitted when a r1 owner is removed - * @param pubKey bytes - r1 owner that has been removed - */ - event R1RemoveOwner(bytes pubKey); - /** * @notice Event emitted when a k1 owner is removed * @param addr address - k1 owner that has been removed */ event K1RemoveOwner(address indexed addr); - /** - * @notice Event emitted when all owners are cleared - */ - event ResetOwners(); - - /** - * @notice Adds a r1 owner to the list of r1 owners - * @dev Can only be called by self or a whitelisted module - * @dev Public Key length must be 64 bytes - * @param pubKey bytes calldata - Public key to add to the list of r1 owners - */ - function r1AddOwner(bytes calldata pubKey) external; - /** * @notice Adds a k1 owner to the list of k1 owners * @dev Can only be called by self or a whitelisted module @@ -51,14 +26,6 @@ interface IOwnerManager { */ function k1AddOwner(address addr) external; - /** - * @notice Removes a r1 owner from the list of r1 owners - * @dev Can only be called by self or a whitelisted module - * @dev Can not remove the last r1 owner - * @param pubKey bytes calldata - Public key to remove from the list of r1 owners - */ - function r1RemoveOwner(bytes calldata pubKey) external; - /** * @notice Removes a k1 owner from the list of k1 owners * @dev Can only be called by self or a whitelisted module @@ -66,21 +33,6 @@ interface IOwnerManager { */ function k1RemoveOwner(address addr) external; - /** - * @notice Clears both r1 owners and k1 owners and adds an r1 owner - * @dev Can only be called by self or a whitelisted module - * @dev Public Key length must be 64 bytes - * @param pubKey bytes calldata - new r1 owner to add - */ - function resetOwners(bytes calldata pubKey) external; - - /** - * @notice Checks if a public key is in the list of r1 owners - * @param pubKey bytes calldata - Public key to check - * @return bool - True if the public key is in the list, false otherwise - */ - function r1IsOwner(bytes calldata pubKey) external view returns (bool); - /** * @notice Checks if an address is in the list of k1 owners * @param addr address - Address to check @@ -88,12 +40,6 @@ interface IOwnerManager { */ function k1IsOwner(address addr) external view returns (bool); - /** - * @notice Returns the list of r1 owners - * @return r1OwnerList bytes[] memory - Array of r1 owner public keys - */ - function r1ListOwners() external view returns (bytes[] memory r1OwnerList); - /** * @notice Returns the list of k1 owners * @return k1OwnerList address[] memory - Array of k1 owner addresses diff --git a/src/interfaces/ISsoAccount.sol b/src/interfaces/ISsoAccount.sol index 45b2c08a..b26acac9 100644 --- a/src/interfaces/ISsoAccount.sol +++ b/src/interfaces/ISsoAccount.sol @@ -30,11 +30,5 @@ interface ISsoAccount is { event FeePaid(); - // TODO: instead of splitting the modules by types here, we can just have a single array that checks the type of the module - // and installs it 7579 style - function initialize( - bytes[] calldata initialValidators, - bytes[] calldata initialModules, - address[] calldata k1Owners - ) external; + function initialize(bytes[] calldata initialValidators, address[] calldata k1Owners) external; } diff --git a/src/interfaces/IValidatorManager.sol b/src/interfaces/IValidatorManager.sol index c30c2e33..cb710cb6 100644 --- a/src/interfaces/IValidatorManager.sol +++ b/src/interfaces/IValidatorManager.sol @@ -6,12 +6,6 @@ pragma solidity ^0.8.24; * @author https://getclave.io */ interface IValidatorManager { - /** - * @notice Event emitted when a r1 validator is added - * @param validator address - Address of the added r1 validator - */ - event R1AddValidator(address indexed validator); - /** * @notice Event emitted when a k1 validator is added * @param validator address - Address of the added k1 validator @@ -24,12 +18,6 @@ interface IValidatorManager { */ event AddModuleValidator(address indexed validator); - /** - * @notice Event emitted when a r1 validator is removed - * @param validator address - Address of the removed r1 validator - */ - event R1RemoveValidator(address indexed validator); - /** * @notice Event emitted when a k1 validator is removed * @param validator address - Address of the removed k1 validator @@ -42,13 +30,6 @@ interface IValidatorManager { */ event RemoveModuleValidator(address indexed validator); - /** - * @notice Adds a validator to the list of r1 validators - * @dev Can only be called by self or a whitelisted module - * @param validator address - Address of the r1 validator to add - */ - function r1AddValidator(address validator) external; - /** * @notice Adds a validator to the list of modular validators * @dev Can only be called by self or a whitelisted module @@ -64,14 +45,6 @@ interface IValidatorManager { */ function k1AddValidator(address validator) external; - /** - * @notice Removes a validator from the list of r1 validators - * @dev Can only be called by self or a whitelisted module - * @dev Can not remove the last validator - * @param validator address - Address of the validator to remove - */ - function r1RemoveValidator(address validator) external; - /** * @notice Removes a validator from the list of k1 validators * @dev Can only be called by self or a whitelisted module @@ -86,13 +59,6 @@ interface IValidatorManager { */ function removeModuleValidator(address validator) external; - /** - * @notice Checks if an address is in the r1 validator list - * @param validator address -Address of the validator to check - * @return True if the address is a validator, false otherwise - */ - function r1IsValidator(address validator) external view returns (bool); - /** * @notice Checks if an address is in the k1 validator list * @param validator address - Address of the validator to check @@ -107,12 +73,6 @@ interface IValidatorManager { */ function isModuleValidator(address validator) external view returns (bool); - /** - * @notice Returns the list of r1 validators - * @return validatorList address[] memory - Array of r1 validator addresses - */ - function r1ListValidators() external view returns (address[] memory validatorList); - /** * @notice Returns the list of k1 validators * @return validatorList address[] memory - Array of k1 validator addresses diff --git a/src/libraries/SsoStorage.sol b/src/libraries/SsoStorage.sol index e98e81b8..cf8d7466 100644 --- a/src/libraries/SsoStorage.sol +++ b/src/libraries/SsoStorage.sol @@ -7,33 +7,17 @@ library SsoStorage { struct Layout { // ┌───────────────────┐ // │ Ownership Data │ - mapping(bytes => bytes) r1Owners; mapping(address => address) k1Owners; uint256[50] __gap_0; // └───────────────────┘ - // ┌───────────────────┐ - // │ Fallback │ - address defaultFallbackContract; // for next version - mapping(bytes4 selector => address) fallbackContractBySelector; - uint256[50] __gap_1; - // └───────────────────┘ - // ┌───────────────────┐ // │ Validation │ - mapping(address => address) r1Validators; mapping(address => address) k1Validators; mapping(address => address) moduleValidators; uint256[50] __gap_2; // └───────────────────┘ - // ┌───────────────────┐ - // │ Module │ - mapping(address => address) modules; - mapping(address => address) execModules; - uint256[50] __gap_3; - // └───────────────────┘ - // ┌───────────────────┐ // │ Hooks │ mapping(address => address) validationHooks; diff --git a/src/managers/ModuleManager.sol b/src/managers/ModuleManager.sol index 96cca418..d63df6b1 100644 --- a/src/managers/ModuleManager.sol +++ b/src/managers/ModuleManager.sol @@ -27,115 +27,6 @@ abstract contract ModuleManager is IModuleManager, Auth { // Low level calls helper library using ExcessivelySafeCall for address; - /// @inheritdoc IModuleManager - function addModule(bytes calldata moduleAndData) external override onlySelfOrModule { - _addModule(moduleAndData); - } - - /// @inheritdoc IModuleManager - function removeModule(address module) external override onlySelfOrModule { - _removeModule(module); - } - - /// @inheritdoc IModuleManager - function executeFromModule(address to, uint256 value, bytes memory data) external override onlyModule { - if (to == address(this)) revert Errors.RECURSIVE_MODULE_CALL(); - - assembly { - let result := call(gas(), to, value, add(data, 0x20), mload(data), 0, 0) - if iszero(result) { - returndatacopy(0, 0, returndatasize()) - revert(0, returndatasize()) - } - } - } - - /// @inheritdoc IModuleManager - function isModule(address addr) external view override returns (bool) { - return _isModule(addr); - } - - /// @inheritdoc IModuleManager - function listModules() external view override returns (address[] memory moduleList) { - moduleList = _modulesLinkedList().list(); - } - - function _addNativeModule(address moduleAddress, bytes memory moduleData) internal { - if (!_supportsModule(moduleAddress)) { - revert Errors.MODULE_ERC165_FAIL(); - } - - _modulesLinkedList().add(moduleAddress); - - IModule(moduleAddress).init(moduleData); - - emit AddModule(moduleAddress); - } - - function _addModule(bytes calldata moduleAndData) internal { - if (moduleAndData.length < 20) { - revert Errors.EMPTY_MODULE_ADDRESS(); - } - - address moduleAddress = address(bytes20(moduleAndData[0:20])); - bytes calldata initData = moduleAndData[20:]; - - if (!_supportsModule(moduleAddress)) { - revert Errors.MODULE_ERC165_FAIL(); - } - - _modulesLinkedList().add(moduleAddress); - - IModule(moduleAddress).init(initData); - - emit AddModule(moduleAddress); - } - - function _addExternalExecutorPermission(address module, bytes calldata data) internal virtual { - _externalExecutorModule().add(module); - - emit AddModule(module); - } - - function _addFallbackModule(address module, bytes calldata data) internal virtual { - SsoStorage.layout().fallbackContractBySelector[bytes4(data[0:4])] = module; - - emit AddModule(module); - } - - function _removeFallbackModule(address module, bytes calldata data) internal virtual { - SsoStorage.layout().fallbackContractBySelector[bytes4(data[0:4])] = address(0); - - emit RemoveModule(module); - } - - function _removeModule(address module) internal { - _modulesLinkedList().remove(module); - - (bool success, ) = module.excessivelySafeCall(gasleft(), 0, abi.encodeWithSelector(IInitable.disable.selector)); - (success); // silence unused local variable warning - - emit RemoveModule(module); - } - - function _isModule(address addr) internal view override returns (bool) { - return _modulesLinkedList().exists(addr); - } - - function _modulesLinkedList() private view returns (mapping(address => address) storage modules) { - modules = SsoStorage.layout().modules; - } - - function _externalExecutorModule() private view returns (mapping(address => address) storage modules) { - modules = SsoStorage.layout().execModules; - } - - function _removeExternalExecutorModule(address module, bytes calldata data) internal { - _externalExecutorModule().remove(module); - - emit RemoveModule(module); - } - function _supportsModule(address module) internal view returns (bool) { // this is pretty dumb, since type(IModule).interfaceId is 0x00000000, but is correct as per ERC165 // context: https://github.com/ethereum/solidity/issues/7856#issuecomment-585337461 diff --git a/src/managers/OwnerManager.sol b/src/managers/OwnerManager.sol index fa5a764c..8ae5aed3 100644 --- a/src/managers/OwnerManager.sol +++ b/src/managers/OwnerManager.sol @@ -11,7 +11,6 @@ import { IOwnerManager } from "../interfaces/IOwnerManager.sol"; /** * @title Manager contract for owners * @notice Abstract contract for managing the owners of the account - * @dev R1 Owners are 64 byte secp256r1 public keys * @dev K1 Owners are secp256k1 addresses * @dev Owners are stored in a linked list * @author https://getclave.io @@ -22,108 +21,46 @@ abstract contract OwnerManager is IOwnerManager, Auth { // Helper library for address to address mappings using AddressLinkedList for mapping(address => address); - /// @inheritdoc IOwnerManager - function r1AddOwner(bytes calldata pubKey) external override onlySelfOrModule { - _r1AddOwner(pubKey); - } - /// @inheritdoc IOwnerManager function k1AddOwner(address addr) external override onlySelfOrModule { _k1AddOwner(addr); } - /// @inheritdoc IOwnerManager - function r1RemoveOwner(bytes calldata pubKey) external override onlySelfOrModule { - _r1RemoveOwner(pubKey); - } - /// @inheritdoc IOwnerManager function k1RemoveOwner(address addr) external override onlySelfOrModule { _k1RemoveOwner(addr); } - /// @inheritdoc IOwnerManager - function resetOwners(bytes calldata pubKey) external override onlySelfOrModule { - _r1ClearOwners(); - _k1ClearOwners(); - - emit ResetOwners(); - - _r1AddOwner(pubKey); - } - - /// @inheritdoc IOwnerManager - function r1IsOwner(bytes calldata pubKey) external view override returns (bool) { - return _r1IsOwner(pubKey); - } - /// @inheritdoc IOwnerManager function k1IsOwner(address addr) external view override returns (bool) { return _k1IsOwner(addr); } - /// @inheritdoc IOwnerManager - function r1ListOwners() external view override returns (bytes[] memory r1OwnerList) { - r1OwnerList = _r1OwnersLinkedList().list(); - } - /// @inheritdoc IOwnerManager function k1ListOwners() external view override returns (address[] memory k1OwnerList) { k1OwnerList = _k1OwnersLinkedList().list(); } - function _r1AddOwner(bytes calldata pubKey) internal { - if (pubKey.length != 64) { - revert Errors.INVALID_PUBKEY_LENGTH(); - } - - _r1OwnersLinkedList().add(pubKey); - - emit R1AddOwner(pubKey); - } - function _k1AddOwner(address addr) internal { _k1OwnersLinkedList().add(addr); emit K1AddOwner(addr); } - function _r1RemoveOwner(bytes calldata pubKey) internal { - _r1OwnersLinkedList().remove(pubKey); - - if (_r1OwnersLinkedList().isEmpty()) { - revert Errors.EMPTY_R1_OWNERS(); - } - - emit R1RemoveOwner(pubKey); - } - function _k1RemoveOwner(address addr) internal { _k1OwnersLinkedList().remove(addr); emit K1RemoveOwner(addr); } - function _r1IsOwner(bytes calldata pubKey) internal view returns (bool) { - return _r1OwnersLinkedList().exists(pubKey); - } - function _k1IsOwner(address addr) internal view returns (bool) { return _k1OwnersLinkedList().exists(addr); } - function _r1OwnersLinkedList() internal view returns (mapping(bytes => bytes) storage r1Owners) { - r1Owners = SsoStorage.layout().r1Owners; - } - function _k1OwnersLinkedList() internal view returns (mapping(address => address) storage k1Owners) { k1Owners = SsoStorage.layout().k1Owners; } - function _r1ClearOwners() private { - _r1OwnersLinkedList().clear(); - } - function _k1ClearOwners() private { _k1OwnersLinkedList().clear(); } diff --git a/src/managers/ValidatorManager.sol b/src/managers/ValidatorManager.sol index 94c8f540..578a6966 100644 --- a/src/managers/ValidatorManager.sol +++ b/src/managers/ValidatorManager.sol @@ -23,11 +23,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { // Interface helper library using ERC165Checker for address; - /// @inheritdoc IValidatorManager - function r1AddValidator(address validator) external override onlySelfOrModule { - _r1AddValidator(validator); - } - function addModuleValidator(address validator, bytes memory initialAccountValidationKey) external onlySelfOrModule { _addModuleValidator(validator, initialAccountValidationKey); } @@ -37,11 +32,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { _k1AddValidator(validator); } - /// @inheritdoc IValidatorManager - function r1RemoveValidator(address validator) external override onlySelfOrModule { - _r1RemoveValidator(validator); - } - /// @inheritdoc IValidatorManager function k1RemoveValidator(address validator) external override onlySelfOrModule { _k1RemoveValidator(validator); @@ -52,11 +42,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { _removeModuleValidator(validator); } - /// @inheritdoc IValidatorManager - function r1IsValidator(address validator) external view override returns (bool) { - return _r1IsValidator(validator); - } - /// @inheritdoc IValidatorManager function k1IsValidator(address validator) external view override returns (bool) { return _k1IsValidator(validator); @@ -67,11 +52,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { return _isModuleValidator(validator); } - /// @inheritdoc IValidatorManager - function r1ListValidators() external view override returns (address[] memory validatorList) { - validatorList = _r1ValidatorsLinkedList().list(); - } - /// @inheritdoc IValidatorManager function k1ListValidators() external view override returns (address[] memory validatorList) { validatorList = _k1ValidatorsLinkedList().list(); @@ -82,16 +62,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { validatorList = _moduleValidatorsLinkedList().list(); } - function _r1AddValidator(address validator) internal { - if (!_supportsR1(validator)) { - revert Errors.VALIDATOR_ERC165_FAIL(); - } - - _r1ValidatorsLinkedList().add(validator); - - emit R1AddValidator(validator); - } - function _addModuleValidator(address validator, bytes memory accountValidationKey) internal { if (!_supportsModuleValidator(validator)) { revert Errors.VALIDATOR_ERC165_FAIL(); @@ -113,16 +83,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { emit K1AddValidator(validator); } - function _r1RemoveValidator(address validator) internal { - _r1ValidatorsLinkedList().remove(validator); - - if (_r1ValidatorsLinkedList().isEmpty()) { - revert Errors.EMPTY_R1_VALIDATORS(); - } - - emit R1RemoveValidator(validator); - } - function _k1RemoveValidator(address validator) internal { _k1ValidatorsLinkedList().remove(validator); @@ -135,10 +95,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { emit RemoveModuleValidator(validator); } - function _r1IsValidator(address validator) internal view returns (bool) { - return _r1ValidatorsLinkedList().exists(validator); - } - function _isModuleValidator(address validator) internal view returns (bool) { return _moduleValidatorsLinkedList().exists(validator); } @@ -147,10 +103,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { return _k1ValidatorsLinkedList().exists(validator); } - function _supportsR1(address validator) internal view returns (bool) { - return validator.supportsInterface(type(IR1Validator).interfaceId); - } - function _supportsK1(address validator) internal view returns (bool) { return validator.supportsInterface(type(IK1Validator).interfaceId); } @@ -159,10 +111,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { return validator.supportsInterface(type(IModuleValidator).interfaceId); } - function _r1ValidatorsLinkedList() private view returns (mapping(address => address) storage r1Validators) { - r1Validators = SsoStorage.layout().r1Validators; - } - function _moduleValidatorsLinkedList() private view returns (mapping(address => address) storage moduleValidators) { moduleValidators = SsoStorage.layout().moduleValidators; } From 3de3d05633a5bb3d0fd26464fd245e5f6fc96cb0 Mon Sep 17 00:00:00 2001 From: Colin Date: Mon, 2 Dec 2024 07:44:23 -0800 Subject: [PATCH 02/17] fix: interface size dropping unused arg --- test/BasicTest.ts | 1 - test/SessionKeyTest.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/test/BasicTest.ts b/test/BasicTest.ts index 39dd125b..70f4a8a3 100644 --- a/test/BasicTest.ts +++ b/test/BasicTest.ts @@ -40,7 +40,6 @@ describe("Basic tests", function () { randomBytes(32), "id", [], - [], [fixtures.wallet.address], ); const deployTxReceipt = await deployTx.wait(); diff --git a/test/SessionKeyTest.ts b/test/SessionKeyTest.ts index 9ae27db9..5b281186 100644 --- a/test/SessionKeyTest.ts +++ b/test/SessionKeyTest.ts @@ -389,7 +389,6 @@ describe("SessionKeyModule tests", function () { const deployTx = await factoryContract.deployProxySsoAccount( randomBytes(32), "id", - [], [sessionKeyPayload], [fixtures.wallet.address], ); From 9f24a1e6dcfbcbbbe1a3d142c29125ad22646fee Mon Sep 17 00:00:00 2001 From: Colin Date: Mon, 2 Dec 2024 18:33:11 -0800 Subject: [PATCH 03/17] fix: single module interface Moving to a single module to elimiate duplicate code --- src/interfaces/IModule.sol | 7 ------- src/interfaces/IModuleValidator.sol | 5 ++++- src/managers/HookManager.sol | 2 -- src/managers/ModuleManager.sol | 4 ++-- src/managers/ValidatorManager.sol | 2 +- src/validators/SessionKeyValidator.sol | 7 ++----- src/validators/WebAuthValidator.sol | 15 +++++++++++++++ 7 files changed, 24 insertions(+), 18 deletions(-) delete mode 100644 src/interfaces/IModule.sol diff --git a/src/interfaces/IModule.sol b/src/interfaces/IModule.sol deleted file mode 100644 index 5cdb9487..00000000 --- a/src/interfaces/IModule.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.24; - -import { IInitable } from "../interfaces/IInitable.sol"; -import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; - -interface IModule is IInitable, IERC165 {} diff --git a/src/interfaces/IModuleValidator.sol b/src/interfaces/IModuleValidator.sol index e576c27c..836b0c22 100644 --- a/src/interfaces/IModuleValidator.sol +++ b/src/interfaces/IModuleValidator.sol @@ -1,11 +1,14 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.24; +import { IInitable } from "../interfaces/IInitable.sol"; +import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + /** * @title Modular validator interface for native AA * @dev Add signature to module or validate existing signatures for acccount */ -interface IModuleValidator { +interface IModuleValidator is IInitable, IERC165 { function handleValidation(bytes32 signedHash, bytes memory signature) external view returns (bool); function addValidationKey(bytes memory key) external returns (bool); diff --git a/src/managers/HookManager.sol b/src/managers/HookManager.sol index 23717a62..dcd5ff81 100644 --- a/src/managers/HookManager.sol +++ b/src/managers/HookManager.sol @@ -191,8 +191,6 @@ abstract contract HookManager is IHookManager, Auth { _executionHooksLinkedList().add(hookAddress); } - IInitable(hookAddress).init(initData); - emit AddHook(hookAddress); } diff --git a/src/managers/ModuleManager.sol b/src/managers/ModuleManager.sol index d63df6b1..6e41c83d 100644 --- a/src/managers/ModuleManager.sol +++ b/src/managers/ModuleManager.sol @@ -8,10 +8,10 @@ import { SsoStorage } from "../libraries/SsoStorage.sol"; import { Auth } from "../auth/Auth.sol"; import { AddressLinkedList } from "../libraries/LinkedList.sol"; import { Errors } from "../libraries/Errors.sol"; -import { IModule } from "../interfaces/IModule.sol"; import { IInitable } from "../interfaces/IInitable.sol"; import { ISsoAccount } from "../interfaces/ISsoAccount.sol"; import { IModuleManager } from "../interfaces/IModuleManager.sol"; +import { IModuleValidator } from "../interfaces/IModuleValidator.sol"; /** * @title Manager contract for modules @@ -30,6 +30,6 @@ abstract contract ModuleManager is IModuleManager, Auth { function _supportsModule(address module) internal view returns (bool) { // this is pretty dumb, since type(IModule).interfaceId is 0x00000000, but is correct as per ERC165 // context: https://github.com/ethereum/solidity/issues/7856#issuecomment-585337461 - return module.supportsInterface(type(IModule).interfaceId); + return module.supportsInterface(type(IModuleValidator).interfaceId); } } diff --git a/src/managers/ValidatorManager.sol b/src/managers/ValidatorManager.sol index 578a6966..2fce7759 100644 --- a/src/managers/ValidatorManager.sol +++ b/src/managers/ValidatorManager.sol @@ -68,7 +68,7 @@ abstract contract ValidatorManager is IValidatorManager, Auth { } _moduleValidatorsLinkedList().add(validator); - IModuleValidator(validator).addValidationKey(accountValidationKey); + IModuleValidator(validator).init(accountValidationKey); emit AddModuleValidator(validator); } diff --git a/src/validators/SessionKeyValidator.sol b/src/validators/SessionKeyValidator.sol index 074b5178..cda006d5 100644 --- a/src/validators/SessionKeyValidator.sol +++ b/src/validators/SessionKeyValidator.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.24; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import { IModule } from "../interfaces/IModule.sol"; import { IValidationHook } from "../interfaces/IHook.sol"; import { IModuleValidator } from "../interfaces/IModuleValidator.sol"; @@ -15,7 +14,7 @@ import { IHookManager } from "../interfaces/IHookManager.sol"; import { IValidatorManager } from "../interfaces/IValidatorManager.sol"; import { SessionLib } from "../libraries/SessionLib.sol"; -contract SessionKeyValidator is IValidationHook, IModuleValidator, IModule { +contract SessionKeyValidator is IValidationHook, IModuleValidator { using SessionLib for SessionLib.SessionStorage; using EnumerableSet for EnumerableSet.Bytes32Set; @@ -76,7 +75,6 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator, IModule { // to prevent recursion, since addHook also calls init if (!_isInitialized(msg.sender)) { IHookManager(msg.sender).addHook(abi.encodePacked(address(this)), true); - IValidatorManager(msg.sender).addModuleValidator(address(this), data); } } @@ -97,8 +95,7 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator, IModule { interfaceId != 0xffffffff && (interfaceId == type(IERC165).interfaceId || interfaceId == type(IValidationHook).interfaceId || - interfaceId == type(IModuleValidator).interfaceId || - interfaceId == type(IModule).interfaceId); + interfaceId == type(IModuleValidator).interfaceId); } // TODO: make the session owner able revoke its own key, in case it was leaked, to prevent further misuse? diff --git a/src/validators/WebAuthValidator.sol b/src/validators/WebAuthValidator.sol index a5cd9feb..054114fb 100644 --- a/src/validators/WebAuthValidator.sol +++ b/src/validators/WebAuthValidator.sol @@ -21,7 +21,22 @@ contract WebAuthValidator is VerifierCaller, IModuleValidator { mapping(string originDomain => mapping(address accountAddress => bytes32)) public lowerKeyHalf; mapping(string originDomain => mapping(address accountAddress => bytes32)) public upperKeyHalf; + function init(bytes calldata key) external { + require(_addValidationKey(key), "failed to init"); + } + function addValidationKey(bytes memory key) external returns (bool) { + return _addValidationKey(key); + } + + function disable() external { + // There's no mapping from account address to domains, + // so there's no way to just delete all the keys + // We can only disconnect the module from the account, + // re-linking it will allow any previous keys + } + + function _addValidationKey(bytes memory key) internal returns (bool) { (bytes32[2] memory key32, string memory originDomain) = abi.decode(key, (bytes32[2], string)); bytes32 initialLowerHalf = lowerKeyHalf[originDomain][msg.sender]; bytes32 initialUpperHalf = upperKeyHalf[originDomain][msg.sender]; From 38d969a80c3a4f6d0d82b9bb64ca3421f20b5250 Mon Sep 17 00:00:00 2001 From: Colin Date: Mon, 2 Dec 2024 22:10:48 -0800 Subject: [PATCH 04/17] fix: remove the whole manager this was unused and too similar to the validator module --- src/SsoAccount.sol | 11 +--------- src/interfaces/IModuleManager.sol | 14 ------------- src/interfaces/ISsoAccount.sol | 2 -- src/managers/ModuleManager.sol | 35 ------------------------------- 4 files changed, 1 insertion(+), 61 deletions(-) delete mode 100644 src/interfaces/IModuleManager.sol delete mode 100644 src/managers/ModuleManager.sol diff --git a/src/SsoAccount.sol b/src/SsoAccount.sol index adbf2da4..4a1b1635 100644 --- a/src/SsoAccount.sol +++ b/src/SsoAccount.sol @@ -11,7 +11,6 @@ import { Utils } from "@matterlabs/zksync-contracts/l2/system-contracts/librarie import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { HookManager } from "./managers/HookManager.sol"; -import { ModuleManager } from "./managers/ModuleManager.sol"; import { TokenCallbackHandler, IERC165 } from "./helpers/TokenCallbackHandler.sol"; @@ -30,15 +29,7 @@ import { ISsoAccount } from "./interfaces/ISsoAccount.sol"; /// @notice This contract is a modular and extensible account implementation with support of /// multi-ownership, custom modules, validation/execution hooks and different signature validation formats. /// @dev Contract is expected to be used as Beacon proxy implementation. -contract SsoAccount is - Initializable, - HookManager, - ModuleManager, - ERC1271Handler, - TokenCallbackHandler, - BatchCaller, - ISsoAccount -{ +contract SsoAccount is Initializable, HookManager, ERC1271Handler, TokenCallbackHandler, BatchCaller, ISsoAccount { // Helper library for the Transaction struct using TransactionHelper for Transaction; diff --git a/src/interfaces/IModuleManager.sol b/src/interfaces/IModuleManager.sol deleted file mode 100644 index 108acce7..00000000 --- a/src/interfaces/IModuleManager.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.24; - -/** - * @title Interface of the manager contract for modules - * @author https://getclave.io - */ -interface IModuleManager { - /** - * @notice Event emitted when a module is removed - * @param module address - Address of the removed module - */ - event RemoveModule(address indexed module); -} diff --git a/src/interfaces/ISsoAccount.sol b/src/interfaces/ISsoAccount.sol index b26acac9..36ae812a 100644 --- a/src/interfaces/ISsoAccount.sol +++ b/src/interfaces/ISsoAccount.sol @@ -9,7 +9,6 @@ import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Rec import { IERC1155Receiver } from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; import { IHookManager } from "./IHookManager.sol"; -import { IModuleManager } from "./IModuleManager.sol"; import { IOwnerManager } from "./IOwnerManager.sol"; import { IValidatorManager } from "./IValidatorManager.sol"; @@ -23,7 +22,6 @@ interface ISsoAccount is IERC721Receiver, IERC1155Receiver, IHookManager, - IModuleManager, IOwnerManager, IValidatorManager, IAccount diff --git a/src/managers/ModuleManager.sol b/src/managers/ModuleManager.sol deleted file mode 100644 index 6e41c83d..00000000 --- a/src/managers/ModuleManager.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.24; - -import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; -import { ExcessivelySafeCall } from "@nomad-xyz/excessively-safe-call/src/ExcessivelySafeCall.sol"; - -import { SsoStorage } from "../libraries/SsoStorage.sol"; -import { Auth } from "../auth/Auth.sol"; -import { AddressLinkedList } from "../libraries/LinkedList.sol"; -import { Errors } from "../libraries/Errors.sol"; -import { IInitable } from "../interfaces/IInitable.sol"; -import { ISsoAccount } from "../interfaces/ISsoAccount.sol"; -import { IModuleManager } from "../interfaces/IModuleManager.sol"; -import { IModuleValidator } from "../interfaces/IModuleValidator.sol"; - -/** - * @title Manager contract for modules - * @notice Abstract contract for managing the enabled modules of the account - * @dev Module addresses are stored in a linked list - * @author https://getclave.io - */ -abstract contract ModuleManager is IModuleManager, Auth { - // Helper library for address to address mappings - using AddressLinkedList for mapping(address => address); - // Interface helper library - using ERC165Checker for address; - // Low level calls helper library - using ExcessivelySafeCall for address; - - function _supportsModule(address module) internal view returns (bool) { - // this is pretty dumb, since type(IModule).interfaceId is 0x00000000, but is correct as per ERC165 - // context: https://github.com/ethereum/solidity/issues/7856#issuecomment-585337461 - return module.supportsInterface(type(IModuleValidator).interfaceId); - } -} From 44b1b29a0355a55bad08a838a06a2b3afbf15c03 Mon Sep 17 00:00:00 2001 From: Colin Date: Tue, 3 Dec 2024 19:41:27 -0800 Subject: [PATCH 05/17] fix: replace modules with hooks This is much more direct path to installing instead of using the install to re-enter the account --- package.json | 6 +- pnpm-lock.yaml | 162 ++++++++++++------------- src/AAFactory.sol | 5 +- src/SsoAccount.sol | 12 +- src/interfaces/ISsoAccount.sol | 6 +- src/managers/HookManager.sol | 8 +- src/validators/SessionKeyValidator.sol | 7 +- test/BasicTest.ts | 1 + test/SessionKeyTest.ts | 11 +- 9 files changed, 118 insertions(+), 100 deletions(-) diff --git a/package.json b/package.json index f4a3cb65..6ef0ecf6 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "eslint-plugin-simple-import-sort": "12.1.1", "ethers": "6.13.2", "globals": "15.9.0", - "hardhat": "^2.22.12", + "hardhat": "^2.22.17", "husky": "9.1.6", "ini": "5.0.0", "lint-staged": "15.2.10", @@ -74,14 +74,14 @@ "nx": "19.8.6", "prettier": "3.3.3", "prettier-plugin-solidity": "^1.4.1", + "solady": "^0.0.273", "ts-node": "10.9.2", "typechain": "8.3.2", "typescript": "5.6.2", "typescript-eslint": "8.7.0", "viem": "^2.21.14", "zksync-ethers": "6.15.0", - "zksync-sso": "0.0.0-beta.2", - "solady": "^0.0.273" + "zksync-sso": "0.0.0-beta.2" }, "packageManager": "pnpm@9.11.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55695e44..118779c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,10 +31,10 @@ importers: version: 0.2.2 '@matterlabs/hardhat-zksync': specifier: 1.2.0 - version: 1.2.0(usgi36jxwmcpnzhrk43hjntexu) + version: 1.2.0(fepeho5lbjwfeubrlam6jwj3im) '@matterlabs/hardhat-zksync-deploy': specifier: 1.5.0 - version: 1.5.0(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2)) + version: 1.5.0(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2)) '@matterlabs/zksync-contracts': specifier: ^0.6.1 version: 0.6.1(@openzeppelin/contracts-upgradeable@4.9.6)(@openzeppelin/contracts@4.9.6) @@ -43,16 +43,16 @@ importers: version: 0.0.1-rc.1 '@nomicfoundation/hardhat-chai-matchers': specifier: 2.0.8 - version: 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(chai@4.5.0)(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + version: 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(chai@4.5.0)(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@nomicfoundation/hardhat-ethers': specifier: 3.0.8 - version: 3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + version: 3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@nomicfoundation/hardhat-toolbox': specifier: ^5.0.0 - version: 5.0.0(cfo2tkb7o3545vb5w3un5hokvy) + version: 5.0.0(g4q45fufb3cpd4wckvbqanslk4) '@nomicfoundation/hardhat-verify': specifier: 2.0.11 - version: 2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + version: 2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@openzeppelin/contracts': specifier: 4.9.6 version: 4.9.6 @@ -88,7 +88,7 @@ importers: version: 0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2) '@typechain/hardhat': specifier: 9.1.0 - version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2))(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(typechain@8.3.2(typescript@5.6.2)) + version: 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2))(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(typechain@8.3.2(typescript@5.6.2)) '@types/chai': specifier: 4.3.20 version: 4.3.20 @@ -132,8 +132,8 @@ importers: specifier: 15.9.0 version: 15.9.0 hardhat: - specifier: ^2.22.12 - version: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + specifier: ^2.22.17 + version: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) husky: specifier: 9.1.6 version: 9.1.6 @@ -4205,8 +4205,8 @@ packages: peerDependencies: hardhat: ^2.0.2 - hardhat@2.22.16: - resolution: {integrity: sha512-d52yQZ09u0roL6GlgJSvtknsBtIuj9JrJ/U8VMzr/wue+gO5v2tQayvOX6llerlR57Zw2EOTQjLAt6RpHvjwHA==} + hardhat@2.22.17: + resolution: {integrity: sha512-tDlI475ccz4d/dajnADUTRc1OJ3H8fpP9sWhXhBPpYsQOg8JHq5xrDimo53UhWPl7KJmAeDCm1bFG74xvpGRpg==} hasBin: true peerDependencies: ts-node: '*' @@ -8011,15 +8011,15 @@ snapshots: - encoding - supports-color - '@matterlabs/hardhat-zksync-deploy@1.5.0(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2))': + '@matterlabs/hardhat-zksync-deploy@1.5.0(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2))': dependencies: - '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) chai: 4.5.0 chalk: 4.1.2 ethers: 6.13.2 fs-extra: 11.2.0 glob: 10.4.5 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) lodash: 4.17.21 sinon: 18.0.1 sinon-chai: 3.7.0(chai@4.5.0)(sinon@18.0.1) @@ -8029,15 +8029,15 @@ snapshots: - encoding - supports-color - '@matterlabs/hardhat-zksync-deploy@1.6.0(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2))': + '@matterlabs/hardhat-zksync-deploy@1.6.0(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2))': dependencies: - '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) chai: 4.5.0 chalk: 4.1.2 ethers: 6.13.2 fs-extra: 11.2.0 glob: 10.4.5 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) lodash: 4.17.21 sinon: 18.0.1 sinon-chai: 3.7.0(chai@4.5.0)(sinon@18.0.1) @@ -8049,13 +8049,13 @@ snapshots: '@matterlabs/hardhat-zksync-ethers@1.2.1(ethers@6.13.2)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)(zksync-ethers@6.15.0(ethers@6.13.2))': dependencies: - '@matterlabs/hardhat-zksync-deploy': 1.5.0(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2)) - '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-deploy': 1.5.0(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2)) + '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) chai: 4.5.0 chalk: 4.1.2 ethers: 6.13.2 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) zksync-ethers: 6.15.0(ethers@6.13.2) transitivePeerDependencies: - bufferutil @@ -8066,15 +8066,15 @@ snapshots: - typescript - utf-8-validate - '@matterlabs/hardhat-zksync-node@1.2.0(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@matterlabs/hardhat-zksync-node@1.2.0(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: - '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) axios: 1.7.7(debug@4.3.7) chai: 4.5.0 chalk: 4.1.2 debug: 4.3.7(supports-color@9.4.0) fs-extra: 11.2.0 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) proxyquire: 2.1.3 sinon: 18.0.1 sinon-chai: 3.7.0(chai@4.5.0)(sinon@18.0.1) @@ -8084,7 +8084,7 @@ snapshots: - encoding - supports-color - '@matterlabs/hardhat-zksync-solc@1.2.5(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@matterlabs/hardhat-zksync-solc@1.2.5(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: '@nomiclabs/hardhat-docker': 2.0.2 chai: 4.5.0 @@ -8092,7 +8092,7 @@ snapshots: debug: 4.3.7(supports-color@9.4.0) dockerode: 4.0.2 fs-extra: 11.2.0 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) proper-lockfile: 4.1.2 semver: 7.6.3 sinon: 18.0.1 @@ -8102,23 +8102,23 @@ snapshots: - encoding - supports-color - '@matterlabs/hardhat-zksync-upgradable@1.8.2(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)': + '@matterlabs/hardhat-zksync-upgradable@1.8.2(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)': dependencies: - '@matterlabs/hardhat-zksync-deploy': 1.6.0(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2)) + '@matterlabs/hardhat-zksync-deploy': 1.6.0(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2)) '@matterlabs/hardhat-zksync-ethers': 1.2.1(ethers@6.13.2)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)(zksync-ethers@6.15.0(ethers@6.13.2)) - '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@openzeppelin/contracts-hardhat-zksync-upgradable': '@openzeppelin/contracts@5.1.0' '@openzeppelin/defender-sdk-base-client': 1.15.2 '@openzeppelin/defender-sdk-deploy-client': 1.15.2(debug@4.3.7) '@openzeppelin/defender-sdk-network-client': 1.15.2(debug@4.3.7) - '@openzeppelin/hardhat-upgrades': 3.5.0(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@openzeppelin/hardhat-upgrades': 3.5.0(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@openzeppelin/upgrades-core': 1.40.0 chalk: 4.1.2 compare-versions: 6.1.1 ethereumjs-util: 7.1.5 ethers: 6.13.2 fs-extra: 11.2.0 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) proper-lockfile: 4.1.2 semver: 7.6.3 solidity-ast: 0.4.59 @@ -8135,18 +8135,18 @@ snapshots: - typescript - utf-8-validate - '@matterlabs/hardhat-zksync-verify@1.7.0(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@matterlabs/hardhat-zksync-verify@1.7.0(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 - '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) axios: 1.7.7(debug@4.3.7) cbor: 9.0.2 chai: 4.5.0 chalk: 4.1.2 debug: 4.3.7(supports-color@9.4.0) - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) semver: 7.6.3 sinon: 18.0.1 sinon-chai: 3.7.0(chai@4.5.0)(sinon@18.0.1) @@ -8154,20 +8154,20 @@ snapshots: - encoding - supports-color - '@matterlabs/hardhat-zksync@1.2.0(usgi36jxwmcpnzhrk43hjntexu)': + '@matterlabs/hardhat-zksync@1.2.0(fepeho5lbjwfeubrlam6jwj3im)': dependencies: - '@matterlabs/hardhat-zksync-deploy': 1.5.0(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2)) + '@matterlabs/hardhat-zksync-deploy': 1.5.0(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(zksync-ethers@6.15.0(ethers@6.13.2)) '@matterlabs/hardhat-zksync-ethers': 1.2.1(ethers@6.13.2)(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)(zksync-ethers@6.15.0(ethers@6.13.2)) - '@matterlabs/hardhat-zksync-node': 1.2.0(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@matterlabs/hardhat-zksync-upgradable': 1.8.2(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) - '@matterlabs/hardhat-zksync-verify': 1.7.0(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-node': 1.2.0(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-solc': 1.2.5(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@matterlabs/hardhat-zksync-upgradable': 1.8.2(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + '@matterlabs/hardhat-zksync-verify': 1.7.0(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@openzeppelin/upgrades-core': 1.40.0 chai: 4.5.0 ethers: 6.13.2 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) sinon: 18.0.1 sinon-chai: 3.7.0(chai@4.5.0)(sinon@18.0.1) zksync-ethers: 6.15.0(ethers@6.13.2) @@ -8296,43 +8296,43 @@ snapshots: '@nomicfoundation/ethereumjs-rlp': 5.0.4 ethereum-cryptography: 0.1.3 - '@nomicfoundation/hardhat-chai-matchers@2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(chai@4.5.0)(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@nomicfoundation/hardhat-chai-matchers@2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(chai@4.5.0)(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@types/chai-as-promised': 7.1.8 chai: 4.5.0 chai-as-promised: 7.1.2(chai@4.5.0) deep-eql: 4.1.4 ethers: 6.13.2 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) ordinal: 1.0.3 - '@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: debug: 4.3.7(supports-color@9.4.0) ethers: 6.13.2 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) lodash.isequal: 4.5.0 transitivePeerDependencies: - supports-color - '@nomicfoundation/hardhat-ignition-ethers@0.15.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-ignition@0.15.8(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/ignition-core@0.15.8)(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@nomicfoundation/hardhat-ignition-ethers@0.15.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-ignition@0.15.8(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/ignition-core@0.15.8)(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-ignition': 0.15.8(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-ignition': 0.15.8(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@nomicfoundation/ignition-core': 0.15.8 ethers: 6.13.2 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) - '@nomicfoundation/hardhat-ignition@0.15.8(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@nomicfoundation/hardhat-ignition@0.15.8(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: - '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@nomicfoundation/ignition-core': 0.15.8 '@nomicfoundation/ignition-ui': 0.15.8 chalk: 4.1.2 debug: 4.3.7(supports-color@9.4.0) fs-extra: 10.1.0 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) json5: 2.2.3 prompts: 2.4.2 transitivePeerDependencies: @@ -8340,40 +8340,40 @@ snapshots: - supports-color - utf-8-validate - '@nomicfoundation/hardhat-network-helpers@1.0.12(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@nomicfoundation/hardhat-network-helpers@1.0.12(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) - '@nomicfoundation/hardhat-toolbox@5.0.0(cfo2tkb7o3545vb5w3un5hokvy)': + '@nomicfoundation/hardhat-toolbox@5.0.0(g4q45fufb3cpd4wckvbqanslk4)': dependencies: - '@nomicfoundation/hardhat-chai-matchers': 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(chai@4.5.0)(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-ignition-ethers': 0.15.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-ignition@0.15.8(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/ignition-core@0.15.8)(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-network-helpers': 1.0.12(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-chai-matchers': 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(chai@4.5.0)(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-ignition-ethers': 0.15.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-ignition@0.15.8(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/ignition-core@0.15.8)(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-network-helpers': 1.0.12(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@typechain/ethers-v6': 0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2))(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(typechain@8.3.2(typescript@5.6.2)) + '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2))(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(typechain@8.3.2(typescript@5.6.2)) '@types/chai': 4.3.20 '@types/mocha': 10.0.8 '@types/node': 20.16.10 chai: 4.5.0 ethers: 6.13.2 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) - hardhat-gas-reporter: 1.0.10(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) - solidity-coverage: 0.8.13(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat-gas-reporter: 1.0.10(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + solidity-coverage: 0.8.13(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) ts-node: 10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2) typechain: 8.3.2(typescript@5.6.2) typescript: 5.6.2 - '@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 cbor: 8.1.0 chalk: 2.4.2 debug: 4.3.7(supports-color@9.4.0) - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) lodash.clonedeep: 4.5.0 semver: 6.3.1 table: 6.8.2 @@ -8740,9 +8740,9 @@ snapshots: - debug - encoding - '@openzeppelin/hardhat-upgrades@3.5.0(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': + '@openzeppelin/hardhat-upgrades@3.5.0(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(@nomicfoundation/hardhat-verify@2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)))(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))': dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) '@openzeppelin/defender-sdk-base-client': 1.15.2 '@openzeppelin/defender-sdk-deploy-client': 1.15.2(debug@4.3.7) '@openzeppelin/defender-sdk-network-client': 1.15.2(debug@4.3.7) @@ -8751,11 +8751,11 @@ snapshots: debug: 4.3.7(supports-color@9.4.0) ethereumjs-util: 7.1.5 ethers: 6.13.2 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) proper-lockfile: 4.1.2 undici: 6.21.0 optionalDependencies: - '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) + '@nomicfoundation/hardhat-verify': 2.0.11(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)) transitivePeerDependencies: - encoding - supports-color @@ -9331,12 +9331,12 @@ snapshots: typechain: 8.3.2(typescript@5.6.2) typescript: 5.6.2 - '@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2))(ethers@6.13.2)(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(typechain@8.3.2(typescript@5.6.2))': + '@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2))(ethers@6.13.2)(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2))(typechain@8.3.2(typescript@5.6.2))': dependencies: '@typechain/ethers-v6': 0.5.1(ethers@6.13.2)(typechain@8.3.2(typescript@5.6.2))(typescript@5.6.2) ethers: 6.13.2 fs-extra: 9.1.0 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) typechain: 8.3.2(typescript@5.6.2) '@types/bn.js@4.11.6': @@ -11648,11 +11648,11 @@ snapshots: optionalDependencies: uglify-js: 3.19.3 - hardhat-gas-reporter@1.0.10(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)): + hardhat-gas-reporter@1.0.10(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)): dependencies: array-uniq: 1.0.3 eth-gas-reporter: 0.2.27 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) sha1: 1.1.1 transitivePeerDependencies: - '@codechecks/client' @@ -11660,7 +11660,7 @@ snapshots: - debug - utf-8-validate - hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2): + hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2): dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 @@ -13642,7 +13642,7 @@ snapshots: solidity-ast@0.4.59: {} - solidity-coverage@0.8.13(hardhat@2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)): + solidity-coverage@0.8.13(hardhat@2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2)): dependencies: '@ethersproject/abi': 5.7.0 '@solidity-parser/parser': 0.18.0 @@ -13653,7 +13653,7 @@ snapshots: ghost-testrpc: 0.0.2 global-modules: 2.0.0 globby: 10.0.2 - hardhat: 2.22.16(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) + hardhat: 2.22.17(ts-node@10.9.2(@swc/core@1.7.26(@swc/helpers@0.5.15))(@types/node@20.16.10)(typescript@5.6.2))(typescript@5.6.2) jsonschema: 1.4.1 lodash: 4.17.21 mocha: 10.7.3 diff --git a/src/AAFactory.sol b/src/AAFactory.sol index 7162e537..fe57503b 100644 --- a/src/AAFactory.sol +++ b/src/AAFactory.sol @@ -41,6 +41,7 @@ contract AAFactory is UpgradeableBeacon { bytes32 _salt, string calldata _uniqueAccountId, bytes[] calldata _initialValidators, + bytes[] calldata _initialHooks, address[] calldata _initialK1Owners ) external returns (address accountAddress) { require(accountMappings[_uniqueAccountId] == address(0), "Account already exists"); @@ -62,8 +63,8 @@ contract AAFactory is UpgradeableBeacon { require(success, "Deployment failed"); (accountAddress) = abi.decode(returnData, (address)); - // Initialize the newly deployed account with validators and K1 owners. - ISsoAccount(accountAddress).initialize(_initialValidators, _initialK1Owners); + // Initialize the newly deployed account with validators, hooks and K1 owners. + ISsoAccount(accountAddress).initialize(_initialValidators, _initialHooks, _initialK1Owners); accountMappings[_uniqueAccountId] = accountAddress; diff --git a/src/SsoAccount.sol b/src/SsoAccount.sol index 4a1b1635..f4d21f4a 100644 --- a/src/SsoAccount.sol +++ b/src/SsoAccount.sol @@ -41,12 +41,22 @@ contract SsoAccount is Initializable, HookManager, ERC1271Handler, TokenCallback /// @dev Sets passkey and passkey validator within account storage /// @param _initialValidators An array of module validator addresses and initial validation keys /// in an ABI encoded format of `abi.encode(validatorAddr,validationKey))`. + /// @param _initialValidationHooks An array of hook module validator addresses and initial validation keys + /// in an ABI encoded format of `abi.encode(validatorAddr,validationKey))`. /// @param _initialK1Owners An array of addresses with full control over the account. - function initialize(bytes[] calldata _initialValidators, address[] calldata _initialK1Owners) external initializer { + function initialize( + bytes[] calldata _initialValidators, + bytes[] calldata _initialValidationHooks, + address[] calldata _initialK1Owners + ) external initializer { for (uint256 i = 0; i < _initialValidators.length; ++i) { (address validatorAddr, bytes memory validationKey) = abi.decode(_initialValidators[i], (address, bytes)); _addModuleValidator(validatorAddr, validationKey); } + for (uint256 i = 0; i < _initialValidationHooks.length; ++i) { + (address validatorAddr, bytes memory validationKey) = abi.decode(_initialValidationHooks[i], (address, bytes)); + _installHook(validatorAddr, validationKey, true); + } for (uint256 i = 0; i < _initialK1Owners.length; ++i) { _k1AddOwner(_initialK1Owners[i]); } diff --git a/src/interfaces/ISsoAccount.sol b/src/interfaces/ISsoAccount.sol index 36ae812a..3705cb17 100644 --- a/src/interfaces/ISsoAccount.sol +++ b/src/interfaces/ISsoAccount.sol @@ -28,5 +28,9 @@ interface ISsoAccount is { event FeePaid(); - function initialize(bytes[] calldata initialValidators, address[] calldata k1Owners) external; + function initialize( + bytes[] calldata initialValidators, + bytes[] calldata initialHooks, + address[] calldata k1Owners + ) external; } diff --git a/src/managers/HookManager.sol b/src/managers/HookManager.sol index dcd5ff81..f40a813f 100644 --- a/src/managers/HookManager.sol +++ b/src/managers/HookManager.sol @@ -179,12 +179,14 @@ abstract contract HookManager is IHookManager, Auth { address hookAddress = address(bytes20(hookAndData[0:20])); + bytes calldata initData = hookAndData[20:]; + _installHook(hookAddress, initData, isValidation); + } + + function _installHook(address hookAddress, bytes memory initData, bool isValidation) internal { if (!_supportsHook(hookAddress, isValidation)) { revert Errors.HOOK_ERC165_FAIL(); } - - bytes calldata initData = hookAndData[20:]; - if (isValidation) { _validationHooksLinkedList().add(hookAddress); } else { diff --git a/src/validators/SessionKeyValidator.sol b/src/validators/SessionKeyValidator.sol index cda006d5..a18c5e1b 100644 --- a/src/validators/SessionKeyValidator.sol +++ b/src/validators/SessionKeyValidator.sol @@ -71,12 +71,7 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator { emit SessionCreated(msg.sender, sessionHash, sessionSpec); } - function init(bytes calldata data) external { - // to prevent recursion, since addHook also calls init - if (!_isInitialized(msg.sender)) { - IHookManager(msg.sender).addHook(abi.encodePacked(address(this)), true); - } - } + function init(bytes calldata data) external {} function disable() external { if (_isInitialized(msg.sender)) { diff --git a/test/BasicTest.ts b/test/BasicTest.ts index 70f4a8a3..39dd125b 100644 --- a/test/BasicTest.ts +++ b/test/BasicTest.ts @@ -40,6 +40,7 @@ describe("Basic tests", function () { randomBytes(32), "id", [], + [], [fixtures.wallet.address], ); const deployTxReceipt = await deployTx.wait(); diff --git a/test/SessionKeyTest.ts b/test/SessionKeyTest.ts index 5b281186..43398a2f 100644 --- a/test/SessionKeyTest.ts +++ b/test/SessionKeyTest.ts @@ -271,7 +271,11 @@ class SessionTester { }; const signedTransaction = await this.sessionAccount.signTransaction(this.aaTransaction); - await expect(provider.broadcastTransaction(signedTransaction)).to.be.reverted; + const txResponse = await provider.broadcastTransaction(signedTransaction); + + // Because this rejects the transaction during validation, we don't get a receipt + expect (txResponse.blockNumber).to.be.null; + expect (await txResponse.confirmations()).to.be.equal(0) }; getLimit(limit?: PartialLimit): SessionLib.UsageLimitStruct { @@ -349,7 +353,7 @@ class SessionTester { } } -describe("SessionKeyModule tests", function () { +describe.only("SessionKeyModule tests", function () { let proxyAccountAddress: string; (hre.network.name == "dockerizedNode" ? it : it.skip)("should deposit funds", async () => { @@ -388,7 +392,8 @@ describe("SessionKeyModule tests", function () { const deployTx = await factoryContract.deployProxySsoAccount( randomBytes(32), - "id", + "session-key-test-id", + [sessionKeyPayload], [sessionKeyPayload], [fixtures.wallet.address], ); From cdb585035c5c6c7d3c6c631101cca31c6406cdaf Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 4 Dec 2024 06:53:19 -0800 Subject: [PATCH 06/17] fix: run all tests removing only locally tests pass --- test/SessionKeyTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SessionKeyTest.ts b/test/SessionKeyTest.ts index 43398a2f..5694e05f 100644 --- a/test/SessionKeyTest.ts +++ b/test/SessionKeyTest.ts @@ -353,7 +353,7 @@ class SessionTester { } } -describe.only("SessionKeyModule tests", function () { +describe("SessionKeyModule tests", function () { let proxyAccountAddress: string; (hre.network.name == "dockerizedNode" ? it : it.skip)("should deposit funds", async () => { From 328703698419c7a8869acd2277a868b0a4622805 Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 4 Dec 2024 07:07:27 -0800 Subject: [PATCH 07/17] fix: revert this to older implemention This broke locally, but now fails in CI, maybe the converse is also true --- test/SessionKeyTest.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/SessionKeyTest.ts b/test/SessionKeyTest.ts index 5694e05f..fb09522d 100644 --- a/test/SessionKeyTest.ts +++ b/test/SessionKeyTest.ts @@ -271,11 +271,14 @@ class SessionTester { }; const signedTransaction = await this.sessionAccount.signTransaction(this.aaTransaction); + expect (provider.broadcastTransaction(signedTransaction)).to.be.reverted; + /* const txResponse = await provider.broadcastTransaction(signedTransaction); // Because this rejects the transaction during validation, we don't get a receipt expect (txResponse.blockNumber).to.be.null; expect (await txResponse.confirmations()).to.be.equal(0) + */ }; getLimit(limit?: PartialLimit): SessionLib.UsageLimitStruct { From 571503f49db208be099e51f5c8780b41095061f1 Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 4 Dec 2024 07:18:29 -0800 Subject: [PATCH 08/17] chore: update CI action name This was recently renamed, and we're still on an older version --- .gitignore | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c7cd9661..192709a5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ node_modules/ # era-test-node era_test_node.log +anvil-zksync.log package-lock.json yarn.lock diff --git a/README.md b/README.md index 9c49f6b6..dd4cd600 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Forked from [Clave](https://github.com/getclave/clave-contracts). 1. Install workspace dependencies with `pnpm install`. 2. Install the latest release of - [Era Test Node](https://github.com/matter-labs/era-test-node). + [Era Test Node](https://github.com/matter-labs/anvil-zksync). 3. Run `pnpm build` to build the contracts. 4. Run `era_test_node run` and `pnpm test` in separate terminals to run the tests. From 9e169755ef8e3b1e62eaee395c6cf55f52d47de7 Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 4 Dec 2024 07:25:10 -0800 Subject: [PATCH 09/17] chore: cleanup test code This wasn't necessary to pass in ci, but now fails locally :( --- test/SessionKeyTest.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/SessionKeyTest.ts b/test/SessionKeyTest.ts index fb09522d..adeb8aa4 100644 --- a/test/SessionKeyTest.ts +++ b/test/SessionKeyTest.ts @@ -272,13 +272,6 @@ class SessionTester { const signedTransaction = await this.sessionAccount.signTransaction(this.aaTransaction); expect (provider.broadcastTransaction(signedTransaction)).to.be.reverted; - /* - const txResponse = await provider.broadcastTransaction(signedTransaction); - - // Because this rejects the transaction during validation, we don't get a receipt - expect (txResponse.blockNumber).to.be.null; - expect (await txResponse.confirmations()).to.be.equal(0) - */ }; getLimit(limit?: PartialLimit): SessionLib.UsageLimitStruct { From 8174fe191fa9c36727a8dcc38f5640f66a6dd7f4 Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 4 Dec 2024 07:47:45 -0800 Subject: [PATCH 10/17] fix: await on test transaction failure --- test/SessionKeyTest.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/SessionKeyTest.ts b/test/SessionKeyTest.ts index adeb8aa4..5d5563d6 100644 --- a/test/SessionKeyTest.ts +++ b/test/SessionKeyTest.ts @@ -271,7 +271,9 @@ class SessionTester { }; const signedTransaction = await this.sessionAccount.signTransaction(this.aaTransaction); - expect (provider.broadcastTransaction(signedTransaction)).to.be.reverted; + // this fails with "receipt should not be null"? + console.log("signedTransaction", signedTransaction); + await expect (provider.broadcastTransaction(signedTransaction)).to.be.reverted; }; getLimit(limit?: PartialLimit): SessionLib.UsageLimitStruct { From 10e557923bd6cde063b77cc0fe143919662e84ad Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 4 Dec 2024 08:10:16 -0800 Subject: [PATCH 11/17] fix: have to await the reverted within expect This is just a test setup issue combined with a era-test-node change --- test/SessionKeyTest.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/SessionKeyTest.ts b/test/SessionKeyTest.ts index 5d5563d6..8fe920af 100644 --- a/test/SessionKeyTest.ts +++ b/test/SessionKeyTest.ts @@ -271,8 +271,6 @@ class SessionTester { }; const signedTransaction = await this.sessionAccount.signTransaction(this.aaTransaction); - // this fails with "receipt should not be null"? - console.log("signedTransaction", signedTransaction); await expect (provider.broadcastTransaction(signedTransaction)).to.be.reverted; }; From 8e472d202fe4fb02e82a913aa3c0ccc2cda2479b Mon Sep 17 00:00:00 2001 From: Colin Date: Thu, 5 Dec 2024 00:42:21 -0800 Subject: [PATCH 12/17] feat: remove k1 validators And finally R1 validator interfaces --- src/handlers/ValidationHandler.sol | 1 - src/interfaces/IValidator.sol | 50 ---------------------------- src/interfaces/IValidatorManager.sol | 39 ---------------------- src/libraries/Errors.sol | 2 -- src/libraries/SsoStorage.sol | 1 - src/managers/ValidatorManager.sol | 49 --------------------------- 6 files changed, 142 deletions(-) delete mode 100644 src/interfaces/IValidator.sol diff --git a/src/handlers/ValidationHandler.sol b/src/handlers/ValidationHandler.sol index 60168c54..89b9d5b9 100644 --- a/src/handlers/ValidationHandler.sol +++ b/src/handlers/ValidationHandler.sol @@ -6,7 +6,6 @@ import { BytesLinkedList } from "../libraries/LinkedList.sol"; import { OwnerManager } from "../managers/OwnerManager.sol"; import { ValidatorManager } from "../managers/ValidatorManager.sol"; -import { IK1Validator, IR1Validator } from "../interfaces/IValidator.sol"; import { IModuleValidator } from "../interfaces/IModuleValidator.sol"; /** diff --git a/src/interfaces/IValidator.sol b/src/interfaces/IValidator.sol deleted file mode 100644 index db62cb72..00000000 --- a/src/interfaces/IValidator.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.24; - -import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; - -/** - * @title secp256r1 ec keys' signature validator interface - * @author https://getclave.io - */ -interface IR1Validator is IERC165 { - /** - * @notice Allows to validate secp256r1 ec signatures - * @param signedHash bytes32 - hash of the data that is signed by the key - * @param signature bytes - signature - * @param pubKey bytes32[2] - public key coordinates array for the x and y values - * @return valid bool - validation result - */ - function validateSignature( - bytes32 signedHash, - bytes calldata signature, - bytes32[2] calldata pubKey - ) external view returns (bool valid); - - /** - * @notice Allows to validate secp256r1 ec signatures - * @param messageHash bytes32 - message hash of the data that is signed by the key - * @param rs bytes32[2] - unwrapped challenge signature points (r & s) - * @param pubKey bytes32[2] - public key coordinates array for the x and y values - * @return valid bool - validation result - */ - function rawVerify( - bytes32 messageHash, - bytes32[2] calldata rs, - bytes32[2] calldata pubKey - ) external view returns (bool valid); -} - -/** - * @title secp256k1 ec keys' signature validator interface - * @author https://getclave.io - */ -interface IK1Validator is IERC165 { - /** - * @notice Allows to validate secp256k1 ec signatures - * @param signedHash bytes32 - hash of the transaction signed by the key - * @param signature bytes - signature - * @return signer address - recovered signer address - */ - function validateSignature(bytes32 signedHash, bytes calldata signature) external view returns (address signer); -} diff --git a/src/interfaces/IValidatorManager.sol b/src/interfaces/IValidatorManager.sol index cb710cb6..b324f9fd 100644 --- a/src/interfaces/IValidatorManager.sol +++ b/src/interfaces/IValidatorManager.sol @@ -6,24 +6,12 @@ pragma solidity ^0.8.24; * @author https://getclave.io */ interface IValidatorManager { - /** - * @notice Event emitted when a k1 validator is added - * @param validator address - Address of the added k1 validator - */ - event K1AddValidator(address indexed validator); - /** * @notice Event emitted when a modular validator is added * @param validator address - Address of the added modular validator */ event AddModuleValidator(address indexed validator); - /** - * @notice Event emitted when a k1 validator is removed - * @param validator address - Address of the removed k1 validator - */ - event K1RemoveValidator(address indexed validator); - /** * @notice Event emitted when a modular validator is removed * @param validator address - Address of the removed modular validator @@ -38,20 +26,6 @@ interface IValidatorManager { */ function addModuleValidator(address validator, bytes memory accountValidationKey) external; - /** - * @notice Adds a validator to the list of k1 validators - * @dev Can only be called by self or a whitelisted module - * @param validator address - Address of the k1 validator to add - */ - function k1AddValidator(address validator) external; - - /** - * @notice Removes a validator from the list of k1 validators - * @dev Can only be called by self or a whitelisted module - * @param validator address - Address of the validator to remove - */ - function k1RemoveValidator(address validator) external; - /** * @notice Removes a validator from the list of modular validators * @dev Can only be called by self or a whitelisted module @@ -59,13 +33,6 @@ interface IValidatorManager { */ function removeModuleValidator(address validator) external; - /** - * @notice Checks if an address is in the k1 validator list - * @param validator address - Address of the validator to check - * @return True if the address is a validator, false otherwise - */ - function k1IsValidator(address validator) external view returns (bool); - /** * @notice Checks if an address is in the modular validator list * @param validator address - Address of the validator to check @@ -73,12 +40,6 @@ interface IValidatorManager { */ function isModuleValidator(address validator) external view returns (bool); - /** - * @notice Returns the list of k1 validators - * @return validatorList address[] memory - Array of k1 validator addresses - */ - function k1ListValidators() external view returns (address[] memory validatorList); - /** * @notice Returns the list of modular validators * @return validatorList address[] memory - Array of modular validator addresses diff --git a/src/libraries/Errors.sol b/src/libraries/Errors.sol index ce2a4acd..2b2e61d4 100644 --- a/src/libraries/Errors.sol +++ b/src/libraries/Errors.sol @@ -28,14 +28,12 @@ library Errors { OWNER MANAGER //////////////////////////////////////////////////////////////*/ - error EMPTY_R1_OWNERS(); error INVALID_PUBKEY_LENGTH(); /*////////////////////////////////////////////////////////////// VALIDATOR MANAGER //////////////////////////////////////////////////////////////*/ - error EMPTY_R1_VALIDATORS(); error VALIDATOR_ERC165_FAIL(); /*////////////////////////////////////////////////////////////// diff --git a/src/libraries/SsoStorage.sol b/src/libraries/SsoStorage.sol index cf8d7466..a089ff8d 100644 --- a/src/libraries/SsoStorage.sol +++ b/src/libraries/SsoStorage.sol @@ -13,7 +13,6 @@ library SsoStorage { // ┌───────────────────┐ // │ Validation │ - mapping(address => address) k1Validators; mapping(address => address) moduleValidators; uint256[50] __gap_2; // └───────────────────┘ diff --git a/src/managers/ValidatorManager.sol b/src/managers/ValidatorManager.sol index 2fce7759..ea9bf20d 100644 --- a/src/managers/ValidatorManager.sol +++ b/src/managers/ValidatorManager.sol @@ -7,7 +7,6 @@ import { Auth } from "../auth/Auth.sol"; import { Errors } from "../libraries/Errors.sol"; import { SsoStorage } from "../libraries/SsoStorage.sol"; import { AddressLinkedList } from "../libraries/LinkedList.sol"; -import { IR1Validator, IK1Validator } from "../interfaces/IValidator.sol"; import { IValidatorManager } from "../interfaces/IValidatorManager.sol"; import { IModuleValidator } from "../interfaces/IModuleValidator.sol"; @@ -27,36 +26,16 @@ abstract contract ValidatorManager is IValidatorManager, Auth { _addModuleValidator(validator, initialAccountValidationKey); } - /// @inheritdoc IValidatorManager - function k1AddValidator(address validator) external override onlySelfOrModule { - _k1AddValidator(validator); - } - - /// @inheritdoc IValidatorManager - function k1RemoveValidator(address validator) external override onlySelfOrModule { - _k1RemoveValidator(validator); - } - ///@inheritdoc IValidatorManager function removeModuleValidator(address validator) external onlySelfOrModule { _removeModuleValidator(validator); } - /// @inheritdoc IValidatorManager - function k1IsValidator(address validator) external view override returns (bool) { - return _k1IsValidator(validator); - } - /// @inheritdoc IValidatorManager function isModuleValidator(address validator) external view override returns (bool) { return _isModuleValidator(validator); } - /// @inheritdoc IValidatorManager - function k1ListValidators() external view override returns (address[] memory validatorList) { - validatorList = _k1ValidatorsLinkedList().list(); - } - /// @inheritdoc IValidatorManager function listModuleValidators() external view override returns (address[] memory validatorList) { validatorList = _moduleValidatorsLinkedList().list(); @@ -73,22 +52,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { emit AddModuleValidator(validator); } - function _k1AddValidator(address validator) internal { - if (!_supportsK1(validator)) { - revert Errors.VALIDATOR_ERC165_FAIL(); - } - - _k1ValidatorsLinkedList().add(validator); - - emit K1AddValidator(validator); - } - - function _k1RemoveValidator(address validator) internal { - _k1ValidatorsLinkedList().remove(validator); - - emit K1RemoveValidator(validator); - } - function _removeModuleValidator(address validator) internal { _moduleValidatorsLinkedList().remove(validator); @@ -99,14 +62,6 @@ abstract contract ValidatorManager is IValidatorManager, Auth { return _moduleValidatorsLinkedList().exists(validator); } - function _k1IsValidator(address validator) internal view returns (bool) { - return _k1ValidatorsLinkedList().exists(validator); - } - - function _supportsK1(address validator) internal view returns (bool) { - return validator.supportsInterface(type(IK1Validator).interfaceId); - } - function _supportsModuleValidator(address validator) internal view returns (bool) { return validator.supportsInterface(type(IModuleValidator).interfaceId); } @@ -114,8 +69,4 @@ abstract contract ValidatorManager is IValidatorManager, Auth { function _moduleValidatorsLinkedList() private view returns (mapping(address => address) storage moduleValidators) { moduleValidators = SsoStorage.layout().moduleValidators; } - - function _k1ValidatorsLinkedList() private view returns (mapping(address => address) storage k1Validators) { - k1Validators = SsoStorage.layout().k1Validators; - } } From 6d3d6a45c1c05b659610de38c570f7215c23a6f8 Mon Sep 17 00:00:00 2001 From: Colin Date: Thu, 5 Dec 2024 12:21:39 -0800 Subject: [PATCH 13/17] fix: cleanup onlySelfOrModule Easy rename after cleanup --- src/auth/Auth.sol | 9 +-------- src/managers/HookManager.sol | 8 ++++++-- src/managers/OwnerManager.sol | 4 ++-- src/managers/ValidatorManager.sol | 4 ++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/auth/Auth.sol b/src/auth/Auth.sol index 1da7f83f..2681b4bb 100644 --- a/src/auth/Auth.sol +++ b/src/auth/Auth.sol @@ -11,11 +11,4 @@ import { Errors } from "../libraries/Errors.sol"; * @notice Abstract contract that organizes authentication logic for the contract * @author https://getclave.io */ -abstract contract Auth is BootloaderAuth, SelfAuth, HookAuth { - modifier onlySelfOrModule() { - if (msg.sender != address(this)) { - revert Errors.NOT_FROM_SELF_OR_MODULE(); - } - _; - } -} +abstract contract Auth is BootloaderAuth, SelfAuth, HookAuth {} diff --git a/src/managers/HookManager.sol b/src/managers/HookManager.sol index f40a813f..a4a6d3f2 100644 --- a/src/managers/HookManager.sol +++ b/src/managers/HookManager.sol @@ -71,12 +71,12 @@ abstract contract HookManager is IHookManager, Auth { } /// @inheritdoc IHookManager - function addHook(bytes calldata hookAndData, bool isValidation) external override onlySelfOrModule { + function addHook(bytes calldata hookAndData, bool isValidation) external override onlySelf { _addHook(hookAndData, isValidation); } /// @inheritdoc IHookManager - function removeHook(address hook, bool isValidation) external override onlySelfOrModule { + function removeHook(address hook, bool isValidation) external override onlySelf { _removeHook(hook, isValidation); } @@ -180,6 +180,7 @@ abstract contract HookManager is IHookManager, Auth { address hookAddress = address(bytes20(hookAndData[0:20])); bytes calldata initData = hookAndData[20:]; + _installHook(hookAddress, initData, isValidation); } @@ -187,12 +188,15 @@ abstract contract HookManager is IHookManager, Auth { if (!_supportsHook(hookAddress, isValidation)) { revert Errors.HOOK_ERC165_FAIL(); } + if (isValidation) { _validationHooksLinkedList().add(hookAddress); } else { _executionHooksLinkedList().add(hookAddress); } + IInitable(hookAddress).init(initData); + emit AddHook(hookAddress); } diff --git a/src/managers/OwnerManager.sol b/src/managers/OwnerManager.sol index 8ae5aed3..99402e26 100644 --- a/src/managers/OwnerManager.sol +++ b/src/managers/OwnerManager.sol @@ -22,12 +22,12 @@ abstract contract OwnerManager is IOwnerManager, Auth { using AddressLinkedList for mapping(address => address); /// @inheritdoc IOwnerManager - function k1AddOwner(address addr) external override onlySelfOrModule { + function k1AddOwner(address addr) external override onlySelf { _k1AddOwner(addr); } /// @inheritdoc IOwnerManager - function k1RemoveOwner(address addr) external override onlySelfOrModule { + function k1RemoveOwner(address addr) external override onlySelf { _k1RemoveOwner(addr); } diff --git a/src/managers/ValidatorManager.sol b/src/managers/ValidatorManager.sol index ea9bf20d..9ef495da 100644 --- a/src/managers/ValidatorManager.sol +++ b/src/managers/ValidatorManager.sol @@ -22,12 +22,12 @@ abstract contract ValidatorManager is IValidatorManager, Auth { // Interface helper library using ERC165Checker for address; - function addModuleValidator(address validator, bytes memory initialAccountValidationKey) external onlySelfOrModule { + function addModuleValidator(address validator, bytes memory initialAccountValidationKey) external onlySelf { _addModuleValidator(validator, initialAccountValidationKey); } ///@inheritdoc IValidatorManager - function removeModuleValidator(address validator) external onlySelfOrModule { + function removeModuleValidator(address validator) external onlySelf { _removeModuleValidator(validator); } From 0f083e53b708e09a18f0ae58d42496ac5171bc35 Mon Sep 17 00:00:00 2001 From: Colin Date: Thu, 5 Dec 2024 12:26:09 -0800 Subject: [PATCH 14/17] feat: validate adding keys during init The normal case appears to be no data, so the key is added elsewhere? --- src/validators/SessionKeyValidator.sol | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/validators/SessionKeyValidator.sol b/src/validators/SessionKeyValidator.sol index a18c5e1b..6670c01e 100644 --- a/src/validators/SessionKeyValidator.sol +++ b/src/validators/SessionKeyValidator.sol @@ -52,12 +52,7 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator { } function addValidationKey(bytes memory sessionData) external returns (bool) { - if (sessionData.length == 0) { - return false; - } - SessionLib.SessionSpec memory sessionSpec = abi.decode(sessionData, (SessionLib.SessionSpec)); - createSession(sessionSpec); - return true; + return _addValidationKey(sessionData); } function createSession(SessionLib.SessionSpec memory sessionSpec) public { @@ -71,7 +66,21 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator { emit SessionCreated(msg.sender, sessionHash, sessionSpec); } - function init(bytes calldata data) external {} + function init(bytes calldata data) external { + // to prevent duplicate inits, since this can be hook plus a validator + if (!_isInitialized(msg.sender) && data.length != 0) { + require(_addValidationKey(data), "init failed"); + } + } + + function _addValidationKey(bytes memory sessionData) internal returns (bool) { + if (sessionData.length == 0) { + return false; + } + SessionLib.SessionSpec memory sessionSpec = abi.decode(sessionData, (SessionLib.SessionSpec)); + createSession(sessionSpec); + return true; + } function disable() external { if (_isInitialized(msg.sender)) { From 2c6e0d4f563716daa16f06e312530686e690b769 Mon Sep 17 00:00:00 2001 From: Colin Date: Thu, 5 Dec 2024 12:37:59 -0800 Subject: [PATCH 15/17] feat: disable validators on removal This matches the behaviour of the hook --- src/managers/HookManager.sol | 3 +-- src/managers/ValidatorManager.sol | 6 ++++++ src/validators/WebAuthValidator.sol | 9 +++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/managers/HookManager.sol b/src/managers/HookManager.sol index a4a6d3f2..4e723f1b 100644 --- a/src/managers/HookManager.sol +++ b/src/managers/HookManager.sol @@ -207,8 +207,7 @@ abstract contract HookManager is IHookManager, Auth { _executionHooksLinkedList().remove(hook); } - (bool success, ) = hook.excessivelySafeCall(gasleft(), 0, abi.encodeWithSelector(IInitable.disable.selector)); - (success); // silence unused local variable warning + hook.excessivelySafeCall(gasleft(), 0, abi.encodeWithSelector(IInitable.disable.selector)); emit RemoveHook(hook); } diff --git a/src/managers/ValidatorManager.sol b/src/managers/ValidatorManager.sol index 9ef495da..99b4fca7 100644 --- a/src/managers/ValidatorManager.sol +++ b/src/managers/ValidatorManager.sol @@ -2,10 +2,12 @@ pragma solidity ^0.8.24; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import { ExcessivelySafeCall } from "@nomad-xyz/excessively-safe-call/src/ExcessivelySafeCall.sol"; import { Auth } from "../auth/Auth.sol"; import { Errors } from "../libraries/Errors.sol"; import { SsoStorage } from "../libraries/SsoStorage.sol"; +import { IInitable } from "../interfaces/IInitable.sol"; import { AddressLinkedList } from "../libraries/LinkedList.sol"; import { IValidatorManager } from "../interfaces/IValidatorManager.sol"; import { IModuleValidator } from "../interfaces/IModuleValidator.sol"; @@ -21,6 +23,8 @@ abstract contract ValidatorManager is IValidatorManager, Auth { using AddressLinkedList for mapping(address => address); // Interface helper library using ERC165Checker for address; + // Low level calls helper library + using ExcessivelySafeCall for address; function addModuleValidator(address validator, bytes memory initialAccountValidationKey) external onlySelf { _addModuleValidator(validator, initialAccountValidationKey); @@ -55,6 +59,8 @@ abstract contract ValidatorManager is IValidatorManager, Auth { function _removeModuleValidator(address validator) internal { _moduleValidatorsLinkedList().remove(validator); + validator.excessivelySafeCall(gasleft(), 0, abi.encodeWithSelector(IInitable.disable.selector)); + emit RemoveModuleValidator(validator); } diff --git a/src/validators/WebAuthValidator.sol b/src/validators/WebAuthValidator.sol index 054114fb..dc69f182 100644 --- a/src/validators/WebAuthValidator.sol +++ b/src/validators/WebAuthValidator.sol @@ -29,11 +29,12 @@ contract WebAuthValidator is VerifierCaller, IModuleValidator { return _addValidationKey(key); } + // There's no mapping from account address to domains, + // so there's no way to just delete all the keys + // We can only disconnect the module from the account, + // re-linking it will allow any previous keys function disable() external { - // There's no mapping from account address to domains, - // so there's no way to just delete all the keys - // We can only disconnect the module from the account, - // re-linking it will allow any previous keys + require(false, "Cannot disable module without removing it from account"); } function _addValidationKey(bytes memory key) internal returns (bool) { From 8c1cbb7f16a99d8fd6e6ba6533b466ddfb8a7df7 Mon Sep 17 00:00:00 2001 From: Colin Date: Fri, 6 Dec 2024 10:05:47 -0800 Subject: [PATCH 16/17] fix: review comments Updating disable to be more robust! --- src/validators/SessionKeyValidator.sol | 27 +++++++++++++++++--------- src/validators/WebAuthValidator.sol | 2 +- test/SessionKeyTest.ts | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/validators/SessionKeyValidator.sol b/src/validators/SessionKeyValidator.sol index 6670c01e..152c1797 100644 --- a/src/validators/SessionKeyValidator.sol +++ b/src/validators/SessionKeyValidator.sol @@ -57,7 +57,7 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator { function createSession(SessionLib.SessionSpec memory sessionSpec) public { bytes32 sessionHash = keccak256(abi.encode(sessionSpec)); - require(_isInitialized(msg.sender), "Account not initialized"); + require(_isHookInitialized(msg.sender), "Account not initialized"); require(sessionSpec.signer != address(0), "Invalid signer"); require(sessions[sessionHash].status[msg.sender] == SessionLib.Status.NotInitialized, "Session already exists"); require(sessionSpec.feeLimit.limitType != SessionLib.LimitType.Unlimited, "Unlimited fee allowance is not safe"); @@ -68,30 +68,31 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator { function init(bytes calldata data) external { // to prevent duplicate inits, since this can be hook plus a validator - if (!_isInitialized(msg.sender) && data.length != 0) { + if (!_isHookAndModuleInitialized(msg.sender) && data.length != 0) { require(_addValidationKey(data), "init failed"); } } function _addValidationKey(bytes memory sessionData) internal returns (bool) { - if (sessionData.length == 0) { - return false; - } SessionLib.SessionSpec memory sessionSpec = abi.decode(sessionData, (SessionLib.SessionSpec)); createSession(sessionSpec); return true; } function disable() external { - if (_isInitialized(msg.sender)) { + if (_isHookInitialized(msg.sender)) { // Here we have to revoke all keys, so that if the module // is installed again later, there will be no active sessions from the past. // Problem: if there are too many keys, this will run out of gas. // Solution: before uninstalling, require that all keys are revoked manually. require(sessionCounter[msg.sender] == 0, "Revoke all keys first"); - IValidatorManager(msg.sender).removeModuleValidator(address(this)); IHookManager(msg.sender).removeHook(address(this), true); } + + // Check module and hook independently so it's not stuck in a bad state + if (_isModuleInitialized(msg.sender)) { + IValidatorManager(msg.sender).removeModuleValidator(address(this)); + } } function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { @@ -122,13 +123,21 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator { * @return true if validator is registered for the account, false otherwise */ function isInitialized(address smartAccount) external view returns (bool) { - return _isInitialized(smartAccount); + return _isHookAndModuleInitialized(smartAccount); } - function _isInitialized(address smartAccount) internal view returns (bool) { + function _isHookAndModuleInitialized(address smartAccount) internal view returns (bool) { + return _isHookInitialized(smartAccount) && _isModuleInitialized(smartAccount); + } + + function _isHookInitialized(address smartAccount) internal view returns (bool) { return IHookManager(smartAccount).isHook(address(this)); } + function _isModuleInitialized(address smartAccount) internal view returns (bool) { + return IValidatorManager(smartAccount).isModuleValidator(address(this)); + } + function validationHook(bytes32 signedHash, Transaction calldata transaction, bytes calldata hookData) external { (bytes memory signature, address validator, ) = abi.decode(transaction.signature, (bytes, address, bytes[])); if (validator != address(this)) { diff --git a/src/validators/WebAuthValidator.sol b/src/validators/WebAuthValidator.sol index dc69f182..02c3ed14 100644 --- a/src/validators/WebAuthValidator.sol +++ b/src/validators/WebAuthValidator.sol @@ -34,7 +34,7 @@ contract WebAuthValidator is VerifierCaller, IModuleValidator { // We can only disconnect the module from the account, // re-linking it will allow any previous keys function disable() external { - require(false, "Cannot disable module without removing it from account"); + revert("Cannot disable module without removing it from account"); } function _addValidationKey(bytes memory key) internal returns (bool) { diff --git a/test/SessionKeyTest.ts b/test/SessionKeyTest.ts index 8fe920af..815405d5 100644 --- a/test/SessionKeyTest.ts +++ b/test/SessionKeyTest.ts @@ -271,7 +271,7 @@ class SessionTester { }; const signedTransaction = await this.sessionAccount.signTransaction(this.aaTransaction); - await expect (provider.broadcastTransaction(signedTransaction)).to.be.reverted; + await expect(provider.broadcastTransaction(signedTransaction)).to.be.reverted; }; getLimit(limit?: PartialLimit): SessionLib.UsageLimitStruct { From c3d2f8eb51d97fa03fcdd5a554d4924e6ba596ee Mon Sep 17 00:00:00 2001 From: Lyova Potyomkin Date: Mon, 9 Dec 2024 07:32:38 +0200 Subject: [PATCH 17/17] fix: move stuff around --- src/validators/SessionKeyValidator.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/validators/SessionKeyValidator.sol b/src/validators/SessionKeyValidator.sol index 152c1797..df51f530 100644 --- a/src/validators/SessionKeyValidator.sol +++ b/src/validators/SessionKeyValidator.sol @@ -80,16 +80,16 @@ contract SessionKeyValidator is IValidationHook, IModuleValidator { } function disable() external { + // Here we have to revoke all keys, so that if the module + // is installed again later, there will be no active sessions from the past. + // Problem: if there are too many keys, this will run out of gas. + // Solution: before uninstalling, require that all keys are revoked manually. + require(sessionCounter[msg.sender] == 0, "Revoke all keys first"); + + // Check module and hook independently so it's not stuck in a bad state if (_isHookInitialized(msg.sender)) { - // Here we have to revoke all keys, so that if the module - // is installed again later, there will be no active sessions from the past. - // Problem: if there are too many keys, this will run out of gas. - // Solution: before uninstalling, require that all keys are revoked manually. - require(sessionCounter[msg.sender] == 0, "Revoke all keys first"); IHookManager(msg.sender).removeHook(address(this), true); } - - // Check module and hook independently so it's not stuck in a bad state if (_isModuleInitialized(msg.sender)) { IValidatorManager(msg.sender).removeModuleValidator(address(this)); }