From e5f23f5712eca14f1f7b14da3fc489794de93157 Mon Sep 17 00:00:00 2001 From: JohnGuilding Date: Wed, 31 Jul 2024 18:06:33 +0100 Subject: [PATCH] Consolidate module & manager into single contract --- script/Deploy7579TestAccount.s.sol | 23 +- script/DeployEmailRecoveryModule.s.sol | 5 +- script/DeploySafeRecovery.s.sol | 5 +- .../DeployUniversalEmailRecoveryModule.s.sol | 5 +- src/EmailRecoveryManager.sol | 188 ++------------- .../GuardianUtils.sol => GuardianManager.sol} | 221 +++++++++--------- src/factories/EmailRecoveryFactory.sol | 30 +-- .../EmailRecoveryUniversalFactory.sol | 44 ++-- src/handlers/EmailRecoverySubjectHandler.sol | 14 +- src/handlers/SafeRecoverySubjectHandler.sol | 14 +- src/interfaces/IEmailRecoveryManager.sol | 51 ---- src/interfaces/IEmailRecoveryModule.sol | 1 - .../IEmailRecoverySubjectHandler.sol | 2 +- src/interfaces/IGuardianManager.sol | 60 +++++ .../IUniversalEmailRecoveryModule.sol | 1 - src/modules/EmailRecoveryModule.sol | 55 ++--- src/modules/UniversalEmailRecoveryModule.sol | 57 ++--- .../EmailRecoveryManager.integration.t.sol | 98 ++++---- test/integration/IntegrationBase.t.sol | 10 +- .../EmailRecoveryModule.t.sol | 20 +- .../EmailRecoveryModuleBase.t.sol | 48 ++-- .../UniversalEmailRecoveryModule.t.sol | 20 +- .../UniversalEmailRecoveryModuleBase.t.sol | 56 ++--- .../SafeRecovery/SafeIntegrationBase.t.sol | 44 ++-- .../SafeRecovery/SafeRecovery.t.sol | 32 +-- .../deployEmailRecoveryModule.t.sol | 29 +-- .../EmailRecoveryManager/acceptGuardian.t.sol | 38 ++- .../acceptanceSubjectTemplates.t.sol | 2 +- .../EmailRecoveryManager/addGuardian.t.sol | 21 +- .../EmailRecoveryManager/cancelRecovery.t.sol | 18 +- .../changeThreshold.t.sol | 23 +- .../completeRecovery.t.sol | 20 +- .../configureRecovery.t.sol | 50 ++-- .../EmailRecoveryManager/constructor.t.sol | 20 +- ...odule.t.sol => deInitRecoveryModule.t.sol} | 31 ++- .../EmailRecoveryManager/getGuardian.t.sol | 5 +- .../getGuardianConfig.t.sol | 8 +- .../getRecoveryConfig.t.sol | 6 +- .../getRecoveryRequest.t.sol | 2 +- .../EmailRecoveryManager/initialize.t.sol | 53 ----- .../processRecovery.t.sol | 28 ++- .../recoverySubjectTemplates.t.sol | 2 +- .../EmailRecoveryManager/removeGuardian.t.sol | 17 +- .../EmailRecoveryManager/setupGuardians.t.sol | 14 +- .../updateRecoveryConfig.t.sol | 21 +- test/unit/EmailRecoveryManagerHarness.sol | 68 ------ test/unit/EmailRecoveryModuleHarness.sol | 26 +++ .../deployUniversalEmailRecoveryModule.t.sol | 28 +-- test/unit/SafeUnitBase.t.sol | 30 +-- test/unit/UnitBase.t.sol | 24 +- .../UniversalEmailRecoveryModuleHarness.sol | 78 ++++++- test/unit/assertErrorSelectors.t.sol | 34 ++- .../validateRecoverySubject.t.sol | 18 +- .../validateRecoverySubject.t.sol | 18 +- .../libraries/GuardianUtils/addGuardian.t.sol | 29 ++- .../GuardianUtils/changeThreshold.t.sol | 31 ++- .../libraries/GuardianUtils/getGuardian.t.sol | 1 - .../GuardianUtils/removeAllGuardians.t.sol | 12 +- .../GuardianUtils/removeGuardian.t.sol | 29 ++- .../GuardianUtils/setupGuardians.t.sol | 43 ++-- .../GuardianUtils/updateGuardianStatus.t.sol | 41 ++-- .../EmailRecoveryModuleBase.t.sol | 36 ++- .../canStartRecoveryRequest.t.sol | 14 +- .../EmailRecoveryModule/constructor.t.sol | 49 ++-- .../getTrustedRecoveryManager.t.sol | 13 -- .../modules/EmailRecoveryModule/recover.t.sol | 17 +- .../canStartRecoveryRequest.t.sol | 18 +- .../constructor.t.sol | 18 +- .../getTrustedRecoveryManager.t.sol | 13 -- .../onInstall.t.sol | 2 +- .../recover.t.sol | 21 +- 71 files changed, 937 insertions(+), 1286 deletions(-) rename src/{libraries/GuardianUtils.sol => GuardianManager.sol} (58%) create mode 100644 src/interfaces/IGuardianManager.sol rename test/unit/EmailRecoveryManager/{deInitRecoveryFromModule.t.sol => deInitRecoveryModule.t.sol} (67%) delete mode 100644 test/unit/EmailRecoveryManager/initialize.t.sol delete mode 100644 test/unit/EmailRecoveryManagerHarness.sol create mode 100644 test/unit/EmailRecoveryModuleHarness.sol delete mode 100644 test/unit/modules/EmailRecoveryModule/getTrustedRecoveryManager.t.sol delete mode 100644 test/unit/modules/UniversalEmailRecoveryModule/getTrustedRecoveryManager.t.sol diff --git a/script/Deploy7579TestAccount.s.sol b/script/Deploy7579TestAccount.s.sol index a5d7941f..957e0952 100644 --- a/script/Deploy7579TestAccount.s.sol +++ b/script/Deploy7579TestAccount.s.sol @@ -5,7 +5,7 @@ import { Script } from "forge-std/Script.sol"; import { console } from "forge-std/console.sol"; import { EmailAccountRecovery } from "ether-email-auth/packages/contracts/src/EmailAccountRecovery.sol"; -import { IEmailRecoveryManager } from "../src/interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { RhinestoneModuleKit } from "modulekit/ModuleKit.sol"; import { OwnableValidator } from "src/test/OwnableValidator.sol"; import { ModuleKitHelpers, ModuleKitUserOp } from "modulekit/ModuleKit.sol"; @@ -38,7 +38,6 @@ contract Deploy7579TestAccountScript is RhinestoneModuleKit, Script { bytes32 accountSalt; address validatorAddr; address recoveryModuleAddr; - address managerAddr; address[] guardians = new address[](0); uint256[] guardianWeights = new uint256[](0); @@ -111,8 +110,6 @@ contract Deploy7579TestAccountScript is RhinestoneModuleKit, Script { }); BootstrapConfig[] memory executors = new BootstrapConfig[](1); - managerAddr = vm.envAddress("RECOVERY_MANAGER"); - require(managerAddr != address(0), "RECOVERY_MANAGER is required"); bytes memory recoveryModuleInstallData = abi.encode( validatorAddr, @@ -140,17 +137,18 @@ contract Deploy7579TestAccountScript is RhinestoneModuleKit, Script { { // Add an EmailAuth guardian - address guardianAddr = - EmailAccountRecovery(managerAddr).computeEmailAuthAddress(account, accountSalt); + address guardianAddr = EmailAccountRecovery(recoveryModuleAddr).computeEmailAuthAddress( + account, accountSalt + ); console.log("Guardian's EmailAuth address", guardianAddr); userOpCalldata = abi.encodeCall( IERC7579Account.execute, ( ModeLib.encodeSimpleSingle(), ExecutionLib.encodeSingle( - address(managerAddr), + address(recoveryModuleAddr), uint256(0), - abi.encodeCall(IEmailRecoveryManager.addGuardian, (guardianAddr, 1)) + abi.encodeCall(IGuardianManager.addGuardian, (guardianAddr, 1)) ) ) ); @@ -183,17 +181,18 @@ contract Deploy7579TestAccountScript is RhinestoneModuleKit, Script { // set threshold to 1. { // Add an EmailAuth guardian - address guardianAddr = - EmailAccountRecovery(managerAddr).computeEmailAuthAddress(account, accountSalt); + address guardianAddr = EmailAccountRecovery(recoveryModuleAddr).computeEmailAuthAddress( + account, accountSalt + ); console.log("Guardian's EmailAuth address", guardianAddr); userOpCalldata = abi.encodeCall( IERC7579Account.execute, ( ModeLib.encodeSimpleSingle(), ExecutionLib.encodeSingle( - address(managerAddr), + address(recoveryModuleAddr), uint256(0), - abi.encodeCall(IEmailRecoveryManager.changeThreshold, 1) + abi.encodeCall(IGuardianManager.changeThreshold, 1) ) ) ); diff --git a/script/DeployEmailRecoveryModule.s.sol b/script/DeployEmailRecoveryModule.s.sol index b3d3ae9e..9d2f0fd3 100644 --- a/script/DeployEmailRecoveryModule.s.sol +++ b/script/DeployEmailRecoveryModule.s.sol @@ -50,9 +50,7 @@ contract DeployEmailRecoveryModuleScript is Script { } { EmailRecoveryFactory factory = EmailRecoveryFactory(_factory); - (address module, address manager, address subjectHandler) = factory - .deployEmailRecoveryModule( - bytes32(uint256(0)), + (address module, address subjectHandler) = factory.deployEmailRecoveryModule( bytes32(uint256(0)), bytes32(uint256(0)), type(EmailRecoverySubjectHandler).creationCode, @@ -62,7 +60,6 @@ contract DeployEmailRecoveryModuleScript is Script { ); console.log("Deployed Email Recovery Module at", vm.toString(module)); - console.log("Deployed Email Recovery Manager at", vm.toString(manager)); console.log("Deployed Email Recovery Handler at", vm.toString(subjectHandler)); vm.stopBroadcast(); } diff --git a/script/DeploySafeRecovery.s.sol b/script/DeploySafeRecovery.s.sol index 358a4e83..6268d902 100644 --- a/script/DeploySafeRecovery.s.sol +++ b/script/DeploySafeRecovery.s.sol @@ -47,9 +47,7 @@ contract DeploySafeRecovery_Script is Script { EmailRecoveryUniversalFactory factory = new EmailRecoveryUniversalFactory(verifier, emailAuthImpl); - (address module, address manager, address subjectHandler) = factory - .deployUniversalEmailRecoveryModule( - bytes32(uint256(0)), + (address module, address subjectHandler) = factory.deployUniversalEmailRecoveryModule( bytes32(uint256(0)), bytes32(uint256(0)), type(SafeRecoverySubjectHandler).creationCode, @@ -61,7 +59,6 @@ contract DeploySafeRecovery_Script is Script { address(new Safe7579Launchpad{ salt: bytes32(uint256(0)) }(entryPoint, registry)); console.log("Deployed Email Recovery Module at ", vm.toString(module)); - console.log("Deployed Email Recovery Manager at ", vm.toString(manager)); console.log("Deployed Email Recovery Handler at ", vm.toString(subjectHandler)); console.log("Deployed Safe 7579 at ", vm.toString(safe7579)); console.log("Deployed Safe 7579 Launchpad at ", vm.toString(safe7579Launchpad)); diff --git a/script/DeployUniversalEmailRecoveryModule.s.sol b/script/DeployUniversalEmailRecoveryModule.s.sol index 342d61e8..590f57bc 100644 --- a/script/DeployUniversalEmailRecoveryModule.s.sol +++ b/script/DeployUniversalEmailRecoveryModule.s.sol @@ -43,9 +43,7 @@ contract DeployUniversalEmailRecoveryModuleScript is Script { } { EmailRecoveryUniversalFactory factory = EmailRecoveryUniversalFactory(_factory); - (address module, address manager, address subjectHandler) = factory - .deployUniversalEmailRecoveryModule( - bytes32(uint256(0)), + (address module, address subjectHandler) = factory.deployUniversalEmailRecoveryModule( bytes32(uint256(0)), bytes32(uint256(0)), type(EmailRecoverySubjectHandler).creationCode, @@ -53,7 +51,6 @@ contract DeployUniversalEmailRecoveryModuleScript is Script { ); console.log("Deployed Email Recovery Module at", vm.toString(module)); - console.log("Deployed Email Recovery Manager at", vm.toString(manager)); console.log("Deployed Email Recovery Handler at", vm.toString(subjectHandler)); vm.stopBroadcast(); } diff --git a/src/EmailRecoveryManager.sol b/src/EmailRecoveryManager.sol index ad8ca279..dde6b0d4 100644 --- a/src/EmailRecoveryManager.sol +++ b/src/EmailRecoveryManager.sol @@ -1,19 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; - import { EmailAccountRecovery } from "ether-email-auth/packages/contracts/src/EmailAccountRecovery.sol"; import { IEmailRecoveryManager } from "./interfaces/IEmailRecoveryManager.sol"; import { IEmailRecoverySubjectHandler } from "./interfaces/IEmailRecoverySubjectHandler.sol"; -import { IEmailRecoveryModule } from "./interfaces/IEmailRecoveryModule.sol"; -import { - EnumerableGuardianMap, - GuardianStorage, - GuardianStatus -} from "./libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "./libraries/GuardianUtils.sol"; +import { GuardianManager } from "./GuardianManager.sol"; +import { GuardianStorage, GuardianStatus } from "./libraries/EnumerableGuardianMap.sol"; /** * @title EmailRecoveryManager @@ -32,10 +25,11 @@ import { GuardianUtils } from "./libraries/GuardianUtils.sol"; * defines and validates the recovery email subjects. Developers can write their own subject * handlers to make specifc subjects for recovering modules */ -contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailRecoveryManager { - using GuardianUtils for mapping(address => GuardianConfig); - using GuardianUtils for mapping(address => EnumerableGuardianMap.AddressToGuardianMap); - +abstract contract EmailRecoveryManager is + EmailAccountRecovery, + GuardianManager, + IEmailRecoveryManager +{ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS & STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ @@ -51,16 +45,6 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco */ address public immutable subjectHandler; - /** - * The recovery module that is responsible for recovering an account - */ - address public emailRecoveryModule; - - /** - * Deployer address stored to prevent frontrunning at initialization - */ - address private immutable deployer; - /** * Account address to recovery config */ @@ -71,27 +55,6 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco */ mapping(address account => RecoveryRequest recoveryRequest) internal recoveryRequests; - /** - * Account to guardian config - */ - mapping(address account => GuardianConfig guardianConfig) internal guardianConfigs; - - /** - * Account address to guardian address to guardian storage - */ - mapping(address account => EnumerableGuardianMap.AddressToGuardianMap guardian) internal - guardiansStorage; - - /** - * @notice Modifier to check recovery status. Reverts if recovery is in process for the account - */ - modifier onlyWhenNotRecovering() { - if (recoveryRequests[msg.sender].currentWeight > 0) { - revert RecoveryInProcess(); - } - _; - } - constructor( address _verifier, address _dkimRegistry, @@ -114,17 +77,6 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco dkimAddr = _dkimRegistry; emailAuthImplementationAddr = _emailAuthImpl; subjectHandler = _subjectHandler; - deployer = msg.sender; - } - - function initialize(address _emailRecoveryModule) external initializer { - if (msg.sender != deployer) { - revert InitializerNotDeployer(); - } - if (_emailRecoveryModule == address(0)) { - revert InvalidRecoveryModule(); - } - emailRecoveryModule = _emailRecoveryModule; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ @@ -234,13 +186,13 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco * @param expiry The expiry time after which the recovery attempt is invalid */ function configureRecovery( - address[] calldata guardians, - uint256[] calldata weights, + address[] memory guardians, + uint256[] memory weights, uint256 threshold, uint256 delay, uint256 expiry ) - external + internal { address account = msg.sender; @@ -250,10 +202,6 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco revert SetupAlreadyCalled(); } - if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToBeRecovered(account)) { - revert RecoveryModuleNotAuthorized(); - } - (uint256 guardianCount, uint256 totalWeight) = setupGuardians(account, guardians, weights, threshold); @@ -325,10 +273,6 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco revert RecoveryInProcess(); } - if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToBeRecovered(account)) { - revert RecoveryModuleNotAuthorized(); - } - // This check ensures GuardianStatus is correct and also implicitly that the // account in email is a valid account GuardianStorage memory guardianStorage = getGuardian(account, guardian); @@ -336,7 +280,7 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco revert InvalidGuardianStatus(guardianStorage.status, GuardianStatus.REQUESTED); } - guardiansStorage.updateGuardianStatus(account, guardian, GuardianStatus.ACCEPTED); + updateGuardianStatus(account, guardian, GuardianStatus.ACCEPTED); guardianConfigs[account].acceptedWeight += guardianStorage.weight; emit GuardianAccepted(account, guardian); @@ -369,10 +313,6 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco templateIdx, subjectParams, address(this) ); - if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToBeRecovered(account)) { - revert RecoveryModuleNotAuthorized(); - } - GuardianConfig memory guardianConfig = guardianConfigs[account]; if (guardianConfig.threshold > guardianConfig.acceptedWeight) { revert ThresholdExceedsAcceptedWeight( @@ -422,7 +362,7 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco * @param account The address of the account for which the recovery is being completed * @param recoveryCalldata The calldata that is passed to recover the validator */ - function completeRecovery(address account, bytes calldata recoveryCalldata) public override { + function completeRecovery(address account, bytes calldata recoveryCalldata) external override { if (account == address(0)) { revert InvalidAccountAddress(); } @@ -452,11 +392,13 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco delete recoveryRequests[account]; - IEmailRecoveryModule(emailRecoveryModule).recover(account, recoveryCalldata); + recover(account, recoveryCalldata); emit RecoveryCompleted(account); } + function recover(address account, bytes calldata recoveryCalldata) internal virtual; + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CANCEL/DE-INIT LOGIC */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ @@ -465,7 +407,7 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco * @notice Cancels the recovery request for the caller's account * @dev Deletes the current recovery request associated with the caller's account */ - function cancelRecovery() external virtual { + function cancelRecovery() external { if (recoveryRequests[msg.sender].currentWeight == 0) { revert NoRecoveryInProcess(); } @@ -480,11 +422,7 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco * should be deinitialized. This should include remove state accociated with an account. * @param account The account to delete state for */ - function deInitRecoveryFromModule(address account) external { - if (emailRecoveryModule != msg.sender) { - revert NotRecoveryModule(); - } - + function deInitRecoveryModule(address account) internal { if (recoveryRequests[account].currentWeight > 0) { revert RecoveryInProcess(); } @@ -492,99 +430,9 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco delete recoveryConfigs[account]; delete recoveryRequests[account]; - guardiansStorage.removeAllGuardians(account); + removeAllGuardians(account); delete guardianConfigs[account]; emit RecoveryDeInitialized(account); } - - /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ - /* GUARDIAN LOGIC */ - /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ - - /** - * @notice Retrieves the guardian configuration for a given account - * @param account The address of the account for which the guardian configuration is being - * retrieved - * @return GuardianConfig The guardian configuration for the specified account - */ - function getGuardianConfig(address account) external view returns (GuardianConfig memory) { - return guardianConfigs[account]; - } - - /** - * @notice Retrieves the guardian storage details for a given guardian and account - * @param account The address of the account associated with the guardian - * @param guardian The address of the guardian - * @return GuardianStorage The guardian storage details for the specified guardian and account - */ - function getGuardian( - address account, - address guardian - ) - public - view - returns (GuardianStorage memory) - { - return guardiansStorage.getGuardianStorage(account, guardian); - } - - /** - * @notice Sets up guardians for a given account with specified weights and threshold - * @dev This function can only be called once and ensures the guardians, weights, and threshold - * are correctly configured - * @param account The address of the account for which guardians are being set up - * @param guardians An array of guardian addresses - * @param weights An array of weights corresponding to each guardian - * @param threshold The threshold weight required for guardians to approve recovery attempts - */ - function setupGuardians( - address account, - address[] calldata guardians, - uint256[] calldata weights, - uint256 threshold - ) - internal - returns (uint256, uint256) - { - return - guardianConfigs.setupGuardians(guardiansStorage, account, guardians, weights, threshold); - } - - /** - * @notice Adds a guardian for the caller's account with a specified weight - * @dev This function can only be called by the account associated with the guardian and only if - * no recovery is in process - * @param guardian The address of the guardian to be added - * @param weight The weight assigned to the guardian - */ - function addGuardian(address guardian, uint256 weight) external onlyWhenNotRecovering { - // Threshold can only be 0 at initialization. - // Check ensures that setup function should be called first - if (guardianConfigs[msg.sender].threshold == 0) { - revert SetupNotCalled(); - } - - guardiansStorage.addGuardian(guardianConfigs, msg.sender, guardian, weight); - } - - /** - * @notice Removes a guardian for the caller's account - * @dev This function can only be called by the account associated with the guardian and only if - * no recovery is in process - * @param guardian The address of the guardian to be removed - */ - function removeGuardian(address guardian) external onlyWhenNotRecovering { - guardiansStorage.removeGuardian(guardianConfigs, msg.sender, guardian); - } - - /** - * @notice Changes the threshold for guardian approvals for the caller's account - * @dev This function can only be called by the account associated with the guardian config and - * only if no recovery is in process - * @param threshold The new threshold for guardian approvals - */ - function changeThreshold(uint256 threshold) external onlyWhenNotRecovering { - guardianConfigs.changeThreshold(msg.sender, threshold); - } } diff --git a/src/libraries/GuardianUtils.sol b/src/GuardianManager.sol similarity index 58% rename from src/libraries/GuardianUtils.sol rename to src/GuardianManager.sol index fa79bcb7..38fbaa76 100644 --- a/src/libraries/GuardianUtils.sol +++ b/src/GuardianManager.sol @@ -1,31 +1,55 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -import { EnumerableGuardianMap, GuardianStorage, GuardianStatus } from "./EnumerableGuardianMap.sol"; -import { IEmailRecoveryManager } from "../interfaces/IEmailRecoveryManager.sol"; +import { + EnumerableGuardianMap, + GuardianStorage, + GuardianStatus +} from "./libraries/EnumerableGuardianMap.sol"; +import { IEmailRecoveryManager } from "./interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "./interfaces/IGuardianManager.sol"; /** - * A helper library to manage guardians + * A contract to manage guardians */ -library GuardianUtils { +abstract contract GuardianManager is IGuardianManager { using EnumerableGuardianMap for EnumerableGuardianMap.AddressToGuardianMap; - event AddedGuardian(address indexed account, address indexed guardian, uint256 weight); - event GuardianStatusUpdated( - address indexed account, address indexed guardian, GuardianStatus newStatus - ); - event RemovedGuardian(address indexed account, address indexed guardian, uint256 weight); - event ChangedThreshold(address indexed account, uint256 threshold); - - error IncorrectNumberOfWeights(uint256 guardianCount, uint256 weightCount); - error ThresholdCannotBeZero(); - error InvalidGuardianAddress(address guardian); - error InvalidGuardianWeight(); - error AddressAlreadyGuardian(); - error ThresholdExceedsTotalWeight(uint256 threshold, uint256 totalWeight); - error StatusCannotBeTheSame(GuardianStatus newStatus); - error SetupNotCalled(); - error AddressNotGuardianForAccount(); + /** + * Account to guardian config + */ + mapping(address account => GuardianManager.GuardianConfig guardianConfig) internal + guardianConfigs; + + /** + * Account address to guardian address to guardian storage + */ + mapping(address account => EnumerableGuardianMap.AddressToGuardianMap guardian) internal + guardiansStorage; + + /** + * @notice Modifier to check recovery status. Reverts if recovery is in process for the account + */ + modifier onlyWhenNotRecovering() { + if (IEmailRecoveryManager(address(this)).getRecoveryRequest(msg.sender).currentWeight > 0) { + revert RecoveryInProcess(); + } + _; + } + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* GUARDIAN LOGIC */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + + /** + * @notice Retrieves the guardian configuration for a given account + * @param account The address of the account for which the guardian configuration is being + * retrieved + * @return GuardianConfig The guardian configuration for the specified account + */ + function getGuardianConfig(address account) public view returns (GuardianConfig memory) { + return guardianConfigs[account]; + } /** * @notice Retrieves the guardian storage details for a given guardian and account @@ -33,12 +57,11 @@ library GuardianUtils { * @param guardian The address of the guardian * @return GuardianStorage The guardian storage details for the specified guardian and account */ - function getGuardianStorage( - mapping(address => EnumerableGuardianMap.AddressToGuardianMap) storage guardiansStorage, + function getGuardian( address account, address guardian ) - internal + public view returns (GuardianStorage memory) { @@ -49,18 +72,15 @@ library GuardianUtils { * @notice Sets up guardians for a given account with specified weights and threshold * @dev This function can only be called once and ensures the guardians, weights, and threshold * are correctly configured - * @param guardiansStorage The guardian storage associated with an account * @param account The address of the account for which guardians are being set up * @param guardians An array of guardian addresses * @param weights An array of weights corresponding to each guardian * @param threshold The threshold weight required for guardians to approve recovery attempts */ function setupGuardians( - mapping(address => IEmailRecoveryManager.GuardianConfig) storage guardianConfigs, - mapping(address => EnumerableGuardianMap.AddressToGuardianMap) storage guardiansStorage, address account, - address[] calldata guardians, - uint256[] calldata weights, + address[] memory guardians, + uint256[] memory weights, uint256 threshold ) internal @@ -77,7 +97,7 @@ library GuardianUtils { } for (uint256 i = 0; i < guardianCount; i++) { - addGuardian(guardiansStorage, guardianConfigs, account, guardians[i], weights[i]); + _addGuardian(account, guardians[i], weights[i]); } uint256 totalWeight = guardianConfigs[account].totalWeight; @@ -91,48 +111,29 @@ library GuardianUtils { } /** - * @notice Updates the status for a guardian - * @param account The address of the account associated with the guardian - * @param guardian The address of the guardian - * @param newStatus The new status for the guardian + * @notice Adds a guardian for the caller's account with a specified weight + * @dev This function can only be called by the account associated with the guardian and only if + * no recovery is in process + * @param guardian The address of the guardian to be added + * @param weight The weight assigned to the guardian */ - function updateGuardianStatus( - mapping(address => EnumerableGuardianMap.AddressToGuardianMap) storage guardiansStorage, - address account, - address guardian, - GuardianStatus newStatus - ) - internal - { - GuardianStorage memory guardianStorage = guardiansStorage[account].get(guardian); - if (newStatus == guardianStorage.status) { - revert StatusCannotBeTheSame(newStatus); + function addGuardian(address guardian, uint256 weight) public onlyWhenNotRecovering { + // Threshold can only be 0 at initialization. + // Check ensures that setup function should be called first + if (guardianConfigs[msg.sender].threshold == 0) { + revert SetupNotCalled(); } - guardiansStorage[account].set({ - key: guardian, - value: GuardianStorage(newStatus, guardianStorage.weight) - }); - emit GuardianStatusUpdated(account, guardian, newStatus); + _addGuardian(msg.sender, guardian, weight); } /** - * @notice Adds a guardian for the caller's account with a specified weight + * @notice Internal fucntion to add a guardian for the caller's account with a specified weight * @dev A guardian is added, but not accepted after this function has been called - * @param guardianConfigs The guardian config storage associated with an account - * @param account The address of the account associated with the guardian * @param guardian The address of the guardian to be added * @param weight The weight assigned to the guardian */ - function addGuardian( - mapping(address => EnumerableGuardianMap.AddressToGuardianMap) storage guardiansStorage, - mapping(address => IEmailRecoveryManager.GuardianConfig) storage guardianConfigs, - address account, - address guardian, - uint256 weight - ) - internal - { + function _addGuardian(address account, address guardian, uint256 weight) internal { if (guardian == address(0) || guardian == account) { revert InvalidGuardianAddress(guardian); } @@ -157,22 +158,15 @@ library GuardianUtils { /** * @notice Removes a guardian for the caller's account - * @param guardianConfigs The guardian config storage associated with an account - * @param account The address of the account associated with the guardian + * @dev This function can only be called by the account associated with the guardian and only if + * no recovery is in process * @param guardian The address of the guardian to be removed */ - function removeGuardian( - mapping(address => EnumerableGuardianMap.AddressToGuardianMap) storage guardiansStorage, - mapping(address => IEmailRecoveryManager.GuardianConfig) storage guardianConfigs, - address account, - address guardian - ) - internal - { - IEmailRecoveryManager.GuardianConfig memory guardianConfig = guardianConfigs[account]; - GuardianStorage memory guardianStorage = guardiansStorage[account].get(guardian); + function removeGuardian(address guardian) external onlyWhenNotRecovering { + GuardianConfig memory guardianConfig = guardianConfigs[msg.sender]; + GuardianStorage memory guardianStorage = guardiansStorage[msg.sender].get(guardian); - bool success = guardiansStorage[account].remove(guardian); + bool success = guardiansStorage[msg.sender].remove(guardian); if (!success) { // false means that the guardian was not present in the map. This serves as a proxy that // the account is not authorized to remove this guardian @@ -185,51 +179,31 @@ library GuardianUtils { revert ThresholdExceedsTotalWeight(newTotalWeight, guardianConfig.threshold); } - guardianConfigs[account].guardianCount--; - guardianConfigs[account].totalWeight -= guardianStorage.weight; + guardianConfigs[msg.sender].guardianCount--; + guardianConfigs[msg.sender].totalWeight -= guardianStorage.weight; if (guardianStorage.status == GuardianStatus.ACCEPTED) { - guardianConfigs[account].acceptedWeight -= guardianStorage.weight; + guardianConfigs[msg.sender].acceptedWeight -= guardianStorage.weight; } - emit RemovedGuardian(account, guardian, guardianStorage.weight); - } - - /** - * @notice Removes all guardians associated with an account - * @dev Does not remove guardian config, this should be modified at the same time as calling - * this function - * @param account The address of the account associated with the guardians - */ - function removeAllGuardians( - mapping(address => EnumerableGuardianMap.AddressToGuardianMap) storage guardiansStorage, - address account - ) - internal - { - guardiansStorage[account].removeAll(guardiansStorage[account].keys()); + emit RemovedGuardian(msg.sender, guardian, guardianStorage.weight); } /** * @notice Changes the threshold for guardian approvals for the caller's account - * @param account The address of the account associated with the guardians + * @dev This function can only be called by the account associated with the guardian config and + * only if no recovery is in process * @param threshold The new threshold for guardian approvals */ - function changeThreshold( - mapping(address => IEmailRecoveryManager.GuardianConfig) storage guardianConfigs, - address account, - uint256 threshold - ) - internal - { + function changeThreshold(uint256 threshold) external onlyWhenNotRecovering { // Threshold can only be 0 at initialization. // Check ensures that setup function should be called first - if (guardianConfigs[account].threshold == 0) { + if (guardianConfigs[msg.sender].threshold == 0) { revert SetupNotCalled(); } // Validate that threshold is smaller than the total weight. - if (threshold > guardianConfigs[account].totalWeight) { - revert ThresholdExceedsTotalWeight(threshold, guardianConfigs[account].totalWeight); + if (threshold > guardianConfigs[msg.sender].totalWeight) { + revert ThresholdExceedsTotalWeight(threshold, guardianConfigs[msg.sender].totalWeight); } // Guardian weight should be at least 1 @@ -237,7 +211,42 @@ library GuardianUtils { revert ThresholdCannotBeZero(); } - guardianConfigs[account].threshold = threshold; - emit ChangedThreshold(account, threshold); + guardianConfigs[msg.sender].threshold = threshold; + emit ChangedThreshold(msg.sender, threshold); + } + + /** + * @notice Updates the status for a guardian + * @param account The address of the account associated with the guardian + * @param guardian The address of the guardian + * @param newStatus The new status for the guardian + */ + function updateGuardianStatus( + address account, + address guardian, + GuardianStatus newStatus + ) + internal + { + GuardianStorage memory guardianStorage = guardiansStorage[account].get(guardian); + if (newStatus == guardianStorage.status) { + revert StatusCannotBeTheSame(newStatus); + } + + guardiansStorage[account].set({ + key: guardian, + value: GuardianStorage(newStatus, guardianStorage.weight) + }); + emit GuardianStatusUpdated(account, guardian, newStatus); + } + + /** + * @notice Removes all guardians associated with an account + * @dev Does not remove guardian config, this should be modified at the same time as calling + * this function + * @param account The address of the account associated with the guardians + */ + function removeAllGuardians(address account) internal { + guardiansStorage[account].removeAll(guardiansStorage[account].keys()); } } diff --git a/src/factories/EmailRecoveryFactory.sol b/src/factories/EmailRecoveryFactory.sol index 40b2f374..7d6ec648 100644 --- a/src/factories/EmailRecoveryFactory.sol +++ b/src/factories/EmailRecoveryFactory.sol @@ -2,19 +2,18 @@ pragma solidity ^0.8.25; import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; -import { EmailRecoveryManager } from "../EmailRecoveryManager.sol"; import { EmailRecoveryModule } from "../modules/EmailRecoveryModule.sol"; /** * @title EmailRecoveryFactory * @notice This contract facilitates the deployment of email recovery modules and their associated - * recovery managers and subject handlers. + * subject handlers. * Create2 is leveraged to ensure deterministic addresses, which assists with module * attestations */ contract EmailRecoveryFactory { /** - * @notice Address of the verifier used by the recovery manager. + * @notice Address of the verifier used by the recovery module. */ address public immutable verifier; @@ -28,7 +27,6 @@ contract EmailRecoveryFactory { event EmailRecoveryModuleDeployed( address emailRecoveryModule, - address emailRecoveryManager, address subjectHandler, address validator, bytes4 functionSelector @@ -46,16 +44,15 @@ contract EmailRecoveryFactory { } /** - * @notice Deploys an email recovery module along with its recovery manager and subject handler + * @notice Deploys an email recovery module along with its subject handler * @dev The subject handler bytecode cannot be determined ahead of time, unlike the recovery - * manager and recovery module, which is why it is passed in directly. In practice, this means a + * module, which is why it is passed in directly. In practice, this means a * developer will write their own subject handler, and then pass the bytecode into this factory * function. * * This deployment function deploys an `EmailRecoveryModule`, which takes a target validator and * target function selector * @param subjectHandlerSalt Salt for the subject handler deployment - * @param recoveryManagerSalt Salt for the recovery manager deployment * @param recoveryModuleSalt Salt for the recovery module deployment * @param subjectHandlerBytecode Bytecode of the subject handler contract * @param dkimRegistry Address of the DKIM registry @@ -63,12 +60,10 @@ contract EmailRecoveryFactory { * @param functionSelector Function selector for the recovery function to be called on the * target validator * @return emailRecoveryModule The deployed email recovery module - * @return emailRecoveryManager The deployed email recovery manager * @return subjectHandler The deployed subject handler */ function deployEmailRecoveryModule( bytes32 subjectHandlerSalt, - bytes32 recoveryManagerSalt, bytes32 recoveryModuleSalt, bytes calldata subjectHandlerBytecode, address dkimRegistry, @@ -76,31 +71,22 @@ contract EmailRecoveryFactory { bytes4 functionSelector ) external - returns (address, address, address) + returns (address, address) { // Deploy subject handler address subjectHandler = Create2.deploy(0, subjectHandlerSalt, subjectHandlerBytecode); - // Deploy recovery manager - address emailRecoveryManager = address( - new EmailRecoveryManager{ salt: recoveryManagerSalt }( - verifier, dkimRegistry, emailAuthImpl, subjectHandler - ) - ); - // Deploy recovery module address emailRecoveryModule = address( new EmailRecoveryModule{ salt: recoveryModuleSalt }( - emailRecoveryManager, validator, functionSelector + verifier, dkimRegistry, emailAuthImpl, subjectHandler, validator, functionSelector ) ); - // Initialize recovery manager with module address - EmailRecoveryManager(emailRecoveryManager).initialize(emailRecoveryModule); emit EmailRecoveryModuleDeployed( - emailRecoveryModule, emailRecoveryManager, subjectHandler, validator, functionSelector + emailRecoveryModule, subjectHandler, validator, functionSelector ); - return (emailRecoveryModule, emailRecoveryManager, subjectHandler); + return (emailRecoveryModule, subjectHandler); } } diff --git a/src/factories/EmailRecoveryUniversalFactory.sol b/src/factories/EmailRecoveryUniversalFactory.sol index a7d2da4d..6bbb6ca4 100644 --- a/src/factories/EmailRecoveryUniversalFactory.sol +++ b/src/factories/EmailRecoveryUniversalFactory.sol @@ -2,13 +2,12 @@ pragma solidity ^0.8.25; import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; -import { EmailRecoveryManager } from "../EmailRecoveryManager.sol"; import { UniversalEmailRecoveryModule } from "../modules/UniversalEmailRecoveryModule.sol"; /** * @title EmailRecoveryFactory * @notice This contract facilitates the deployment of universal email recovery modules and their - * associated recovery managers and subject handlers. + * associated subject handlers. * Create2 is leveraged to ensure deterministic addresses, which assists with module * attestations */ @@ -16,9 +15,7 @@ contract EmailRecoveryUniversalFactory { address public immutable verifier; address public immutable emailAuthImpl; - event UniversalEmailRecoveryModuleDeployed( - address emailRecoveryModule, address emailRecoveryManager, address subjectHandler - ); + event UniversalEmailRecoveryModuleDeployed(address emailRecoveryModule, address subjectHandler); error InvalidVerifier(); error InvalidEmailAuthImpl(); @@ -35,59 +32,46 @@ contract EmailRecoveryUniversalFactory { } /** - * @notice Deploys a universal email recovery module along with its recovery manager and subject - * handler + * @notice Deploys a universal email recovery module along with its subject handler * @dev The subject handler bytecode cannot be determined ahead of time, unlike the recovery - * manager and recovery module, which is why it is passed in directly. In practice, this means a + * module, which is why it is passed in directly. In practice, this means a * developer will write their own subject handler, and then pass the bytecode into this factory * function. The universal recovery module should have a relatively stable subject handler, * however, developers may want to write a generic subject handler in a slightly different way, * or even in a non-english lanaguage, so the bytecode is still passed in here directly. * - * This deployment function deploys an `UniversalEmailRecoveryModule`, which only takes the - * target emailRecoveryManager. The target validator and target function selector are set when a - * module is installed. This is part of what makes the module generic for recovering any - * validator + * This deployment function deploys an `UniversalEmailRecoveryModule`, which takes the + * target verifier, dkim registry, EmailAuth implementation and subject handler. The target + * validator and target function selector are set when a module is installed. This is part of + * what makes the module generic for recovering any validator * @param subjectHandlerSalt Salt for the subject handler deployment - * @param recoveryManagerSalt Salt for the recovery manager deployment * @param recoveryModuleSalt Salt for the recovery module deployment * @param subjectHandlerBytecode Bytecode of the subject handler contract * @param dkimRegistry Address of the DKIM registry. * @return emailRecoveryModule The deployed email recovery module - * @return emailRecoveryManager The deployed email recovery manager * @return subjectHandler The deployed subject handler */ function deployUniversalEmailRecoveryModule( bytes32 subjectHandlerSalt, - bytes32 recoveryManagerSalt, bytes32 recoveryModuleSalt, bytes calldata subjectHandlerBytecode, address dkimRegistry ) external - returns (address, address, address) + returns (address, address) { // Deploy subject handler address subjectHandler = Create2.deploy(0, subjectHandlerSalt, subjectHandlerBytecode); - // Deploy recovery manager - address emailRecoveryManager = address( - new EmailRecoveryManager{ salt: recoveryManagerSalt }( - verifier, dkimRegistry, emailAuthImpl, subjectHandler - ) - ); - // Deploy recovery module address emailRecoveryModule = address( - new UniversalEmailRecoveryModule{ salt: recoveryModuleSalt }(emailRecoveryManager) + new UniversalEmailRecoveryModule{ salt: recoveryModuleSalt }( + verifier, dkimRegistry, emailAuthImpl, subjectHandler + ) ); - // Initialize recovery manager with module address - EmailRecoveryManager(emailRecoveryManager).initialize(emailRecoveryModule); - emit UniversalEmailRecoveryModuleDeployed( - emailRecoveryModule, emailRecoveryManager, subjectHandler - ); + emit UniversalEmailRecoveryModuleDeployed(emailRecoveryModule, subjectHandler); - return (emailRecoveryModule, emailRecoveryManager, subjectHandler); + return (emailRecoveryModule, subjectHandler); } } diff --git a/src/handlers/EmailRecoverySubjectHandler.sol b/src/handlers/EmailRecoverySubjectHandler.sol index d934967e..3efc5b0c 100644 --- a/src/handlers/EmailRecoverySubjectHandler.sol +++ b/src/handlers/EmailRecoverySubjectHandler.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.25; import { IEmailRecoverySubjectHandler } from "../interfaces/IEmailRecoverySubjectHandler.sol"; -import { EmailRecoveryManager } from "../EmailRecoveryManager.sol"; import { StringUtils } from "../libraries/StringUtils.sol"; /** @@ -119,13 +118,13 @@ contract EmailRecoverySubjectHandler is IEmailRecoverySubjectHandler { * @notice Validates the subject params for an acceptance email * @param templateIdx The index of the template used for the recovery request * @param subjectParams The subject parameters of the recovery email - * @param recoveryManager The recovery manager address. Used to help with validation + * @param expectedRecoveryModule The recovery module address. Used to help with validation * @return accountInEmail The account address in the acceptance email */ function validateRecoverySubject( uint256 templateIdx, bytes[] calldata subjectParams, - address recoveryManager + address expectedRecoveryModule ) public view @@ -148,11 +147,10 @@ contract EmailRecoverySubjectHandler is IEmailRecoverySubjectHandler { revert InvalidAccount(); } - // Even though someone could use a malicious contract as the recoveryManager argument, it - // does not matter in this case as this is only used as part of the recovery flow in the - // recovery manager. Passing the recovery manager in the constructor here would result - // in a circular dependency - address expectedRecoveryModule = EmailRecoveryManager(recoveryManager).emailRecoveryModule(); + // Even though someone could use a malicious contract as the expectedRecoveryModule + // argument, it does not matter in this case as this is only used as part of the recovery + // flow in the recovery module. Passing the recovery module in the constructor here would + // result in a circular dependency if (recoveryModuleInEmail == address(0) || recoveryModuleInEmail != expectedRecoveryModule) { revert InvalidRecoveryModule(recoveryModuleInEmail); diff --git a/src/handlers/SafeRecoverySubjectHandler.sol b/src/handlers/SafeRecoverySubjectHandler.sol index f312a48f..74aff2fe 100644 --- a/src/handlers/SafeRecoverySubjectHandler.sol +++ b/src/handlers/SafeRecoverySubjectHandler.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.25; import { IEmailRecoverySubjectHandler } from "../interfaces/IEmailRecoverySubjectHandler.sol"; import { ISafe } from "../interfaces/ISafe.sol"; -import { EmailRecoveryManager } from "../EmailRecoveryManager.sol"; /** * Handler contract that defines subject templates and how to validate them @@ -124,13 +123,13 @@ contract SafeRecoverySubjectHandler is IEmailRecoverySubjectHandler { * @notice Validates the subject params for an acceptance email * @param templateIdx The index of the template used for the recovery request * @param subjectParams The subject parameters of the recovery email - * @param recoveryManager The recovery manager address. Used to help with validation + * @param expectedRecoveryModule The recovery module address. Used to help with validation * @return accountInEmail The account address in the acceptance email */ function validateRecoverySubject( uint256 templateIdx, bytes[] calldata subjectParams, - address recoveryManager + address expectedRecoveryModule ) public view @@ -158,11 +157,10 @@ contract SafeRecoverySubjectHandler is IEmailRecoverySubjectHandler { revert InvalidNewOwner(newOwnerInEmail); } - // Even though someone could use a malicious contract as the recoveryManager argument, it - // does not matter in this case as this is only used as part of the recovery flow in the - // recovery manager. Passing the recovery manager in the constructor here would result - // in a circular dependency - address expectedRecoveryModule = EmailRecoveryManager(recoveryManager).emailRecoveryModule(); + // Even though someone could use a malicious contract as the expectedRecoveryModule + // argument, it does not matter in this case as this is only used as part of the recovery + // flow in the recovery module. Passing the recovery module in the constructor here would + // result in a circular dependency if (recoveryModuleInEmail == address(0) || recoveryModuleInEmail != expectedRecoveryModule) { revert InvalidRecoveryModule(recoveryModuleInEmail); diff --git a/src/interfaces/IEmailRecoveryManager.sol b/src/interfaces/IEmailRecoveryManager.sol index 37386985..7a73d004 100644 --- a/src/interfaces/IEmailRecoveryManager.sol +++ b/src/interfaces/IEmailRecoveryManager.sol @@ -34,22 +34,6 @@ interface IEmailRecoveryManager { // recovery attempt } - /** - * A struct representing the values required for guardian configuration - * Config should be maintained over subsequent recovery attempts unless explicitly modified - */ - struct GuardianConfig { - uint256 guardianCount; // total count for all guardians - uint256 totalWeight; // combined weight for all guardians. Important for checking that - // thresholds are valid. - uint256 acceptedWeight; // combined weight for all accepted guardians. This is separated - // from totalWeight as it is important to prevent recovery starting without enough - // accepted guardians to meet the threshold. Storing this in a variable avoids the need - // to loop over accepted guardians whenever checking if a recovery attempt can be - // started without being broken - uint256 threshold; // the threshold required to successfully process a recovery attempt - } - /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ @@ -74,7 +58,6 @@ interface IEmailRecoveryManager { ERRORS //////////////////////////////////////////////////////////////////////////*/ - error RecoveryInProcess(); error InvalidVerifier(); error InvalidDkimRegistry(); error InvalidEmailAuthImpl(); @@ -83,7 +66,6 @@ interface IEmailRecoveryManager { error InvalidRecoveryModule(); error SetupAlreadyCalled(); error AccountNotConfigured(); - error RecoveryModuleNotAuthorized(); error DelayMoreThanExpiry(uint256 delay, uint256 expiry); error RecoveryWindowTooShort(uint256 recoveryWindow); error ThresholdExceedsAcceptedWeight(uint256 threshold, uint256 acceptedWeight); @@ -97,8 +79,6 @@ interface IEmailRecoveryManager { error RecoveryRequestExpired(uint256 blockTimestamp, uint256 executeBefore); error InvalidCalldataHash(bytes32 calldataHash, bytes32 expectedCalldataHash); error NoRecoveryInProcess(); - error NotRecoveryModule(); - error SetupNotCalled(); /*////////////////////////////////////////////////////////////////////////// FUNCTIONS @@ -108,38 +88,7 @@ interface IEmailRecoveryManager { function getRecoveryRequest(address account) external view returns (RecoveryRequest memory); - function configureRecovery( - address[] memory guardians, - uint256[] memory weights, - uint256 threshold, - uint256 delay, - uint256 expiry - ) - external; - function updateRecoveryConfig(RecoveryConfig calldata recoveryConfig) external; - function deInitRecoveryFromModule(address account) external; - function cancelRecovery() external; - - /*////////////////////////////////////////////////////////////////////////// - GUARDIAN LOGIC - //////////////////////////////////////////////////////////////////////////*/ - - function getGuardianConfig(address account) external view returns (GuardianConfig memory); - - function getGuardian( - address account, - address guardian - ) - external - view - returns (GuardianStorage memory); - - function addGuardian(address guardian, uint256 weight) external; - - function removeGuardian(address guardian) external; - - function changeThreshold(uint256 threshold) external; } diff --git a/src/interfaces/IEmailRecoveryModule.sol b/src/interfaces/IEmailRecoveryModule.sol index f5e27bec..2847b8d4 100644 --- a/src/interfaces/IEmailRecoveryModule.sol +++ b/src/interfaces/IEmailRecoveryModule.sol @@ -4,5 +4,4 @@ pragma solidity ^0.8.25; interface IEmailRecoveryModule { function isAuthorizedToBeRecovered(address account) external returns (bool); function canStartRecoveryRequest(address smartAccount) external view returns (bool); - function recover(address account, bytes memory recoveryCalldata) external; } diff --git a/src/interfaces/IEmailRecoverySubjectHandler.sol b/src/interfaces/IEmailRecoverySubjectHandler.sol index aeca8a46..5a851a54 100644 --- a/src/interfaces/IEmailRecoverySubjectHandler.sol +++ b/src/interfaces/IEmailRecoverySubjectHandler.sol @@ -32,7 +32,7 @@ interface IEmailRecoverySubjectHandler { function validateRecoverySubject( uint256 templateIdx, bytes[] memory subjectParams, - address recoveryManager + address expectedRecoveryModule ) external view diff --git a/src/interfaces/IGuardianManager.sol b/src/interfaces/IGuardianManager.sol new file mode 100644 index 00000000..dbdee7b8 --- /dev/null +++ b/src/interfaces/IGuardianManager.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { + EnumerableGuardianMap, + GuardianStorage, + GuardianStatus +} from "../libraries/EnumerableGuardianMap.sol"; + +interface IGuardianManager { + /** + * A struct representing the values required for guardian configuration + * Config should be maintained over subsequent recovery attempts unless explicitly modified + */ + struct GuardianConfig { + uint256 guardianCount; // total count for all guardians + uint256 totalWeight; // combined weight for all guardians. Important for checking that + // thresholds are valid. + uint256 acceptedWeight; // combined weight for all accepted guardians. This is separated + // from totalWeight as it is important to prevent recovery starting without enough + // accepted guardians to meet the threshold. Storing this in a variable avoids the need + // to loop over accepted guardians whenever checking if a recovery attempt can be + // started without being broken + uint256 threshold; // the threshold required to successfully process a recovery attempt + } + + event AddedGuardian(address indexed account, address indexed guardian, uint256 weight); + event GuardianStatusUpdated( + address indexed account, address indexed guardian, GuardianStatus newStatus + ); + event RemovedGuardian(address indexed account, address indexed guardian, uint256 weight); + event ChangedThreshold(address indexed account, uint256 threshold); + + error RecoveryInProcess(); + error IncorrectNumberOfWeights(uint256 guardianCount, uint256 weightCount); + error ThresholdCannotBeZero(); + error InvalidGuardianAddress(address guardian); + error InvalidGuardianWeight(); + error AddressAlreadyGuardian(); + error ThresholdExceedsTotalWeight(uint256 threshold, uint256 totalWeight); + error StatusCannotBeTheSame(GuardianStatus newStatus); + error SetupNotCalled(); + error AddressNotGuardianForAccount(); + + function getGuardianConfig(address account) external view returns (GuardianConfig memory); + + function getGuardian( + address account, + address guardian + ) + external + view + returns (GuardianStorage memory); + + function addGuardian(address guardian, uint256 weight) external; + + function removeGuardian(address guardian) external; + + function changeThreshold(uint256 threshold) external; +} diff --git a/src/interfaces/IUniversalEmailRecoveryModule.sol b/src/interfaces/IUniversalEmailRecoveryModule.sol index 37806354..97bc05c6 100644 --- a/src/interfaces/IUniversalEmailRecoveryModule.sol +++ b/src/interfaces/IUniversalEmailRecoveryModule.sol @@ -10,7 +10,6 @@ interface IUniversalEmailRecoveryModule { external view returns (bool); - function recover(address account, bytes memory recoveryData) external; /** * Returns validators in reverse order that they were added */ diff --git a/src/modules/EmailRecoveryModule.sol b/src/modules/EmailRecoveryModule.sol index d0574554..e8d222bd 100644 --- a/src/modules/EmailRecoveryModule.sol +++ b/src/modules/EmailRecoveryModule.sol @@ -6,29 +6,24 @@ import { IERC7579Account } from "erc7579/interfaces/IERC7579Account.sol"; import { IModule } from "erc7579/interfaces/IERC7579Module.sol"; import { ISafe } from "../interfaces/ISafe.sol"; import { IEmailRecoveryModule } from "../interfaces/IEmailRecoveryModule.sol"; -import { IEmailRecoveryManager } from "../interfaces/IEmailRecoveryManager.sol"; +import { EmailRecoveryManager } from "../EmailRecoveryManager.sol"; +import { GuardianManager } from "../GuardianManager.sol"; /** * @title EmailRecoveryModule * @notice This contract provides a simple mechanism for recovering account validators by * permissioning certain functions to be called on validators. It facilitates recovery by - * integration with a trusted email recovery manager. The module defines how a recovery request is - * executed on a validator, while the trusted recovery manager defines what a valid - * recovery request is. + * integration with the email recovery manager contract. The module defines how a recovery request + * is executed on a validator, while the recovery manager defines what a valid recovery request is. * * This recovery module targets a specific validator, so this contract should be deployed per * validator */ -contract EmailRecoveryModule is ERC7579ExecutorBase, IEmailRecoveryModule { +contract EmailRecoveryModule is EmailRecoveryManager, ERC7579ExecutorBase, IEmailRecoveryModule { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS & STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ - /** - * Trusted email recovery manager contract that handles recovery requests - */ - address public immutable emailRecoveryManager; - /** * Validator being recovered */ @@ -47,16 +42,20 @@ contract EmailRecoveryModule is ERC7579ExecutorBase, IEmailRecoveryModule { event RecoveryExecuted(address indexed account, address indexed validator); error InvalidSelector(bytes4 selector); - error InvalidManager(); error InvalidOnInstallData(); error InvalidValidator(address validator); - error NotTrustedRecoveryManager(); error RecoveryNotAuthorizedForAccount(); - constructor(address _emailRecoveryManager, address _validator, bytes4 _selector) { - if (_emailRecoveryManager == address(0)) { - revert InvalidManager(); - } + constructor( + address verifier, + address dkimRegistry, + address emailAuthImpl, + address subjectHandler, + address _validator, + bytes4 _selector + ) + EmailRecoveryManager(verifier, dkimRegistry, emailAuthImpl, subjectHandler) + { if (_validator == address(0)) { revert InvalidValidator(_validator); } @@ -69,7 +68,6 @@ contract EmailRecoveryModule is ERC7579ExecutorBase, IEmailRecoveryModule { revert InvalidSelector(_selector); } - emailRecoveryManager = _emailRecoveryManager; validator = _validator; selector = _selector; } @@ -107,13 +105,7 @@ contract EmailRecoveryModule is ERC7579ExecutorBase, IEmailRecoveryModule { } authorized[msg.sender] = true; - _execute({ - to: emailRecoveryManager, - value: 0, - data: abi.encodeCall( - IEmailRecoveryManager.configureRecovery, (guardians, weights, threshold, delay, expiry) - ) - }); + configureRecovery(guardians, weights, threshold, delay, expiry); } /** @@ -122,7 +114,7 @@ contract EmailRecoveryModule is ERC7579ExecutorBase, IEmailRecoveryModule { */ function onUninstall(bytes calldata /* data */ ) external { authorized[msg.sender] = false; - IEmailRecoveryManager(emailRecoveryManager).deInitRecoveryFromModule(msg.sender); + deInitRecoveryModule(msg.sender); } /** @@ -131,7 +123,7 @@ contract EmailRecoveryModule is ERC7579ExecutorBase, IEmailRecoveryModule { * @return true if the module is initialized, false otherwise */ function isInitialized(address account) external view returns (bool) { - return IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(account).threshold != 0; + return getGuardianConfig(account).threshold != 0; } /** @@ -149,8 +141,7 @@ contract EmailRecoveryModule is ERC7579ExecutorBase, IEmailRecoveryModule { * @return true if the recovery request can be started, false otherwise */ function canStartRecoveryRequest(address account) external view returns (bool) { - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(account); + GuardianConfig memory guardianConfig = getGuardianConfig(account); return guardianConfig.acceptedWeight >= guardianConfig.threshold; } @@ -160,16 +151,12 @@ contract EmailRecoveryModule is ERC7579ExecutorBase, IEmailRecoveryModule { /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** - * @notice Executes recovery on a validator. Must be called by the trusted recovery manager + * @notice Executes recovery on a validator. Called from the recovery manager * @param account The account to execute recovery for * @param recoveryCalldata The recovery calldata that should be executed on the validator * being recovered */ - function recover(address account, bytes calldata recoveryCalldata) external { - if (msg.sender != emailRecoveryManager) { - revert NotTrustedRecoveryManager(); - } - + function recover(address account, bytes calldata recoveryCalldata) internal override { if (!authorized[account]) { revert RecoveryNotAuthorizedForAccount(); } diff --git a/src/modules/UniversalEmailRecoveryModule.sol b/src/modules/UniversalEmailRecoveryModule.sol index 74e9b8fc..fb41a073 100644 --- a/src/modules/UniversalEmailRecoveryModule.sol +++ b/src/modules/UniversalEmailRecoveryModule.sol @@ -7,20 +7,23 @@ import { IModule } from "erc7579/interfaces/IERC7579Module.sol"; import { ISafe } from "../interfaces/ISafe.sol"; import { SentinelListLib, SENTINEL, ZERO_ADDRESS } from "sentinellist/SentinelList.sol"; import { IUniversalEmailRecoveryModule } from "../interfaces/IUniversalEmailRecoveryModule.sol"; -import { IEmailRecoveryManager } from "../interfaces/IEmailRecoveryManager.sol"; +import { EmailRecoveryManager } from "../EmailRecoveryManager.sol"; /** * @title UniversalEmailRecoveryModule * @notice This contract provides a simple mechanism for recovering account validators by * permissioning certain functions to be called on validators. It facilitates recovery by - * integration with a trusted email recovery manager. The module defines how a recovery request is - * executed on a validator, while the trusted recovery manager defines what a valid - * recovery request is + * integration with the email recovery manager contract. The module defines how a recovery request + * is executed on a validator, while the recovery manager defines what a valid recovery request is. * * This recovery module is generic and does not target a specific validator. An account may add * multiple validators to this recovery module */ -contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRecoveryModule { +contract UniversalEmailRecoveryModule is + EmailRecoveryManager, + ERC7579ExecutorBase, + IUniversalEmailRecoveryModule +{ using SentinelListLib for SentinelListLib.SentinelList; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ @@ -32,11 +35,6 @@ contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRec */ uint256 public constant MAX_VALIDATORS = 32; - /** - * Trusted email recovery manager contract that handles recovery requests - */ - address public immutable emailRecoveryManager; - event NewValidatorRecovery( address indexed account, address indexed validator, bytes4 recoverySelector ); @@ -45,13 +43,11 @@ contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRec ); event RecoveryExecuted(address indexed account, address indexed validator); - error InvalidManager(); error InvalidSelector(bytes4 selector); error RecoveryModuleNotInitialized(); error InvalidOnInstallData(); error InvalidValidator(address validator); error MaxValidatorsReached(); - error NotTrustedRecoveryManager(); /** * Account address to validator list @@ -94,12 +90,14 @@ contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRec _; } - constructor(address _emailRecoveryManager) { - if (_emailRecoveryManager == address(0)) { - revert InvalidManager(); - } - emailRecoveryManager = _emailRecoveryManager; - } + constructor( + address verifier, + address dkimRegistry, + address emailAuthImpl, + address subjectHandler + ) + EmailRecoveryManager(verifier, dkimRegistry, emailAuthImpl, subjectHandler) + { } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONFIG */ @@ -132,13 +130,7 @@ contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRec validators[msg.sender].init(); allowValidatorRecovery(validator, isInstalledContext, initialSelector); - _execute({ - to: emailRecoveryManager, - value: 0, - data: abi.encodeCall( - IEmailRecoveryManager.configureRecovery, (guardians, weights, threshold, delay, expiry) - ) - }); + configureRecovery(guardians, weights, threshold, delay, expiry); } /** @@ -225,7 +217,7 @@ contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRec validators[msg.sender].popAll(); validatorCount[msg.sender] = 0; - IEmailRecoveryManager(emailRecoveryManager).deInitRecoveryFromModule(msg.sender); + deInitRecoveryModule(msg.sender); } /** @@ -234,7 +226,7 @@ contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRec * @return true if the module is initialized, false otherwise */ function isInitialized(address account) public view returns (bool) { - return IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(account).threshold != 0; + return getGuardianConfig(account).threshold != 0; } /** @@ -260,8 +252,7 @@ contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRec view returns (bool) { - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(account); + GuardianConfig memory guardianConfig = getGuardianConfig(account); return guardianConfig.acceptedWeight >= guardianConfig.threshold && validators[account].contains(validator); @@ -272,16 +263,12 @@ contract UniversalEmailRecoveryModule is ERC7579ExecutorBase, IUniversalEmailRec /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** - * @notice Executes recovery on a validator. Must be called by the trusted recovery manager + * @notice Executes recovery on a validator. Called from the recovery manager * @param account The account to execute recovery for * @param recoveryData The recovery calldata that should be executed on the validator being * recovered, along with the target validator */ - function recover(address account, bytes calldata recoveryData) external { - if (msg.sender != emailRecoveryManager) { - revert NotTrustedRecoveryManager(); - } - + function recover(address account, bytes calldata recoveryData) internal override { (address validator, bytes memory recoveryCalldata) = abi.decode(recoveryData, (address, bytes)); diff --git a/test/integration/EmailRecoveryManager/EmailRecoveryManager.integration.t.sol b/test/integration/EmailRecoveryManager/EmailRecoveryManager.integration.t.sol index 365d519a..78fc4fce 100644 --- a/test/integration/EmailRecoveryManager/EmailRecoveryManager.integration.t.sol +++ b/test/integration/EmailRecoveryManager/EmailRecoveryManager.integration.t.sol @@ -7,7 +7,7 @@ import { MODULE_TYPE_EXECUTOR, MODULE_TYPE_VALIDATOR } from "modulekit/external/ import { EmailAuthMsg } from "ether-email-auth/packages/contracts/src/EmailAuth.sol"; import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; import { OwnableValidator } from "src/test/OwnableValidator.sol"; @@ -32,8 +32,14 @@ contract EmailRecoveryManager_Integration_Test is EmailAuthMsg memory emailAuthMsg = getAcceptanceEmailAuthMessage(accountAddress1, guardians1[0]); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + vm.expectRevert( + abi.encodeWithSelector( + IEmailRecoveryManager.InvalidGuardianStatus.selector, + uint256(GuardianStatus.NONE), + uint256(GuardianStatus.REQUESTED) + ) + ); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function test_RevertWhen_HandleRecoveryCalled_BeforeTimeStampChanged() public { @@ -43,7 +49,7 @@ contract EmailRecoveryManager_Integration_Test is getRecoveryEmailAuthMessage(accountAddress1, guardians1[0], calldataHash1); vm.expectRevert("invalid timestamp"); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } function test_RevertWhen_HandleAcceptanceCalled_DuringRecovery() public { @@ -55,8 +61,8 @@ contract EmailRecoveryManager_Integration_Test is EmailAuthMsg memory emailAuthMsg = getAcceptanceEmailAuthMessage(accountAddress1, guardians1[1]); - vm.expectRevert(IEmailRecoveryManager.RecoveryInProcess.selector); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + vm.expectRevert(IGuardianManager.RecoveryInProcess.selector); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function test_RevertWhen_HandleAcceptanceCalled_AfterRecoveryProcessedButBeforeCompleteRecovery( @@ -72,8 +78,8 @@ contract EmailRecoveryManager_Integration_Test is EmailAuthMsg memory emailAuthMsg = getAcceptanceEmailAuthMessage(accountAddress1, guardians1[2]); - vm.expectRevert(IEmailRecoveryManager.RecoveryInProcess.selector); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + vm.expectRevert(IGuardianManager.RecoveryInProcess.selector); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function test_HandleNewAcceptanceSucceeds_AfterCompleteRecovery() public { @@ -83,12 +89,12 @@ contract EmailRecoveryManager_Integration_Test is handleRecovery(accountAddress1, guardians1[0], calldataHash1); handleRecovery(accountAddress1, guardians1[1], calldataHash1); vm.warp(block.timestamp + delay); - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); acceptGuardian(accountAddress1, guardians1[2]); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress1, guardians1[2]); + emailRecoveryModule.getGuardian(accountAddress1, guardians1[2]); assertEq(uint256(guardianStorage.status), uint256(GuardianStatus.ACCEPTED)); assertEq(guardianStorage.weight, uint256(1)); } @@ -102,7 +108,7 @@ contract EmailRecoveryManager_Integration_Test is getRecoveryEmailAuthMessage(accountAddress1, guardians1[0], calldataHash1); vm.expectRevert(); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } function test_RevertWhen_HandleRecoveryCalled_BeforeHandleAcceptance() public { @@ -110,7 +116,7 @@ contract EmailRecoveryManager_Integration_Test is getRecoveryEmailAuthMessage(accountAddress1, guardians1[0], calldataHash1); vm.expectRevert("guardian is not deployed"); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } function test_RevertWhen_HandleRecoveryCalled_DuringRecoveryWithoutGuardianBeingDeployed() @@ -125,7 +131,7 @@ contract EmailRecoveryManager_Integration_Test is getRecoveryEmailAuthMessage(accountAddress1, guardians1[2], calldataHash1); vm.expectRevert("guardian is not deployed"); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } function test_RevertWhen_HandleRecoveryCalled_AfterRecoveryProcessedButBeforeCompleteRecovery() @@ -141,7 +147,7 @@ contract EmailRecoveryManager_Integration_Test is getRecoveryEmailAuthMessage(accountAddress1, guardians1[2], calldataHash1); vm.expectRevert("guardian is not deployed"); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } // function test_RevertWhen_HandleRecoveryCalled_AfterCompleteRecovery() public { @@ -151,13 +157,13 @@ contract EmailRecoveryManager_Integration_Test is // handleRecovery(accountAddress1, guardian1, calldataHash1); // handleRecovery(accountAddress1, guardian2, calldataHash1); // vm.warp(block.timestamp + delay); - // emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); + // emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); // EmailAuthMsg memory emailAuthMsg = // getRecoveryEmailAuthMessage(accountAddress1, guardian1, calldataHash1); // // vm.expectRevert("email nullifier already used"); // FIXME: - // emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + // emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); // } function test_RevertWhen_CompleteRecoveryCalled_BeforeConfigureRecovery() public { @@ -166,14 +172,14 @@ contract EmailRecoveryManager_Integration_Test is vm.stopPrank(); vm.expectRevert(IEmailRecoveryManager.NoRecoveryConfigured.selector); - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); } function test_RevertWhen_CompleteRecoveryCalled_BeforeHandleAcceptance() public { vm.expectRevert( abi.encodeWithSelector(IEmailRecoveryManager.NotEnoughApprovals.selector, 0, threshold) ); - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); } function test_RevertWhen_CompleteRecoveryCalled_BeforeProcessRecovery() public { @@ -182,38 +188,16 @@ contract EmailRecoveryManager_Integration_Test is vm.expectRevert( abi.encodeWithSelector(IEmailRecoveryManager.NotEnoughApprovals.selector, 0, threshold) ); - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); - } - - function test_TryConfigureAndAcceptanceFunctionsWhenModuleNotInstalled() public { - vm.prank(accountAddress1); - instance1.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, ""); - vm.stopPrank(); - - vm.startPrank(accountAddress1); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.configureRecovery( - guardians1, guardianWeights, threshold, delay, expiry - ); - vm.stopPrank(); - - EmailAuthMsg memory emailAuthMsg = - getAcceptanceEmailAuthMessage(accountAddress1, guardians1[0]); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); - - emailAuthMsg = getAcceptanceEmailAuthMessage(accountAddress1, guardians1[0]); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); } function test_TryRecoverFunctionsWhenModuleNotInstalled() public { EmailAuthMsg memory emailAuthMsg = getAcceptanceEmailAuthMessage(accountAddress1, guardians1[0]); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); emailAuthMsg = getAcceptanceEmailAuthMessage(accountAddress1, guardians1[1]); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); vm.prank(accountAddress1); instance1.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, ""); @@ -222,12 +206,24 @@ contract EmailRecoveryManager_Integration_Test is vm.warp(12 seconds); emailAuthMsg = getRecoveryEmailAuthMessage(accountAddress1, guardians1[0], calldataHash1); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + vm.expectRevert( + abi.encodeWithSelector( + IEmailRecoveryManager.InvalidGuardianStatus.selector, + uint256(GuardianStatus.NONE), + uint256(GuardianStatus.ACCEPTED) + ) + ); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); emailAuthMsg = getRecoveryEmailAuthMessage(accountAddress1, guardians1[1], calldataHash1); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + vm.expectRevert( + abi.encodeWithSelector( + IEmailRecoveryManager.InvalidGuardianStatus.selector, + uint256(GuardianStatus.NONE), + uint256(GuardianStatus.ACCEPTED) + ) + ); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } function test_TryCompleteRecoveryWhenModuleNotInstalled() public { @@ -236,7 +232,7 @@ contract EmailRecoveryManager_Integration_Test is vm.stopPrank(); vm.expectRevert(IEmailRecoveryManager.NoRecoveryConfigured.selector); - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); } function test_StaleRecoveryRequest() public { @@ -254,15 +250,15 @@ contract EmailRecoveryManager_Integration_Test is IEmailRecoveryManager.RecoveryRequestExpired.selector, block.timestamp, executeAfter ) ); - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); // Can cancel recovery even when stale vm.startPrank(accountAddress1); - emailRecoveryManager.cancelRecovery(); + emailRecoveryModule.cancelRecovery(); vm.stopPrank(); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress1); + emailRecoveryModule.getRecoveryRequest(accountAddress1); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 0); diff --git a/test/integration/IntegrationBase.t.sol b/test/integration/IntegrationBase.t.sol index e5fbb099..4a572e01 100644 --- a/test/integration/IntegrationBase.t.sol +++ b/test/integration/IntegrationBase.t.sol @@ -15,7 +15,7 @@ import { MockGroth16Verifier } from "src/test/MockGroth16Verifier.sol"; abstract contract IntegrationBase is RhinestoneModuleKit, Test { // ZK Email contracts and variables address zkEmailDeployer = vm.addr(1); - ECDSAOwnedDKIMRegistry ecdsaOwnedDkimRegistry; + ECDSAOwnedDKIMRegistry dkimRegistry; MockGroth16Verifier verifier; EmailAuth emailAuthImpl; @@ -58,14 +58,14 @@ abstract contract IntegrationBase is RhinestoneModuleKit, Test { // Create ZK Email contracts vm.startPrank(zkEmailDeployer); - ecdsaOwnedDkimRegistry = new ECDSAOwnedDKIMRegistry(zkEmailDeployer); - string memory signedMsg = ecdsaOwnedDkimRegistry.computeSignedMsg( - ecdsaOwnedDkimRegistry.SET_PREFIX(), selector, domainName, publicKeyHash + dkimRegistry = new ECDSAOwnedDKIMRegistry(zkEmailDeployer); + string memory signedMsg = dkimRegistry.computeSignedMsg( + dkimRegistry.SET_PREFIX(), selector, domainName, publicKeyHash ); bytes32 digest = ECDSA.toEthSignedMessageHash(bytes(signedMsg)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, digest); bytes memory signature = abi.encodePacked(r, s, v); - ecdsaOwnedDkimRegistry.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature); + dkimRegistry.setDKIMPublicKeyHash(selector, domainName, publicKeyHash, signature); verifier = new MockGroth16Verifier(); emailAuthImpl = new EmailAuth(); diff --git a/test/integration/OwnableValidatorRecovery/EmailRecoveryModule/EmailRecoveryModule.t.sol b/test/integration/OwnableValidatorRecovery/EmailRecoveryModule/EmailRecoveryModule.t.sol index 90474b8a..8a055bf2 100644 --- a/test/integration/OwnableValidatorRecovery/EmailRecoveryModule/EmailRecoveryModule.t.sol +++ b/test/integration/OwnableValidatorRecovery/EmailRecoveryModule/EmailRecoveryModule.t.sol @@ -23,14 +23,14 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is // Accept guardian 1 acceptGuardian(accountAddress1, guardians1[0]); GuardianStorage memory guardianStorage1 = - emailRecoveryManager.getGuardian(accountAddress1, guardians1[0]); + emailRecoveryModule.getGuardian(accountAddress1, guardians1[0]); assertEq(uint256(guardianStorage1.status), uint256(GuardianStatus.ACCEPTED)); assertEq(guardianStorage1.weight, uint256(1)); // Accept guardian 2 acceptGuardian(accountAddress1, guardians1[1]); GuardianStorage memory guardianStorage2 = - emailRecoveryManager.getGuardian(accountAddress1, guardians1[1]); + emailRecoveryModule.getGuardian(accountAddress1, guardians1[1]); assertEq(uint256(guardianStorage2.status), uint256(GuardianStatus.ACCEPTED)); assertEq(guardianStorage2.weight, uint256(2)); @@ -39,7 +39,7 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is // handle recovery request for guardian 1 handleRecovery(accountAddress1, guardians1[0], calldataHash1); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress1); + emailRecoveryModule.getRecoveryRequest(accountAddress1); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 1); @@ -48,7 +48,7 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is uint256 executeAfter = block.timestamp + delay; uint256 executeBefore = block.timestamp + expiry; handleRecovery(accountAddress1, guardians1[1], calldataHash1); - recoveryRequest = emailRecoveryManager.getRecoveryRequest(accountAddress1); + recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress1); assertEq(recoveryRequest.executeAfter, executeAfter); assertEq(recoveryRequest.executeBefore, executeBefore); assertEq(recoveryRequest.currentWeight, 3); @@ -57,9 +57,9 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is vm.warp(block.timestamp + delay); // Complete recovery - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); - recoveryRequest = emailRecoveryManager.getRecoveryRequest(accountAddress1); + recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress1); address updatedOwner = validator.owners(accountAddress1); assertEq(recoveryRequest.executeAfter, 0); @@ -87,7 +87,7 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is // GuardianStatus.ACCEPTED // ) // ); - // emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + // emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); // } // function test_Recover_CannotMixAccountHandleRecovery() public { @@ -109,7 +109,7 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is // GuardianStatus.ACCEPTED // ) // ); - // emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + // emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); // } // Helper function @@ -126,7 +126,7 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is handleRecovery(account, guardians1[0], calldataHash); handleRecovery(account, guardians1[1], calldataHash); vm.warp(block.timestamp + delay); - emailRecoveryManager.completeRecovery(account, recoveryCalldata); + emailRecoveryModule.completeRecovery(account, recoveryCalldata); } // function test_Recover_RotatesMultipleOwnersSuccessfully() public { @@ -164,6 +164,6 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is // ); // vm.expectRevert("invalid timestamp"); - // emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + // emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); // } } diff --git a/test/integration/OwnableValidatorRecovery/EmailRecoveryModule/EmailRecoveryModuleBase.t.sol b/test/integration/OwnableValidatorRecovery/EmailRecoveryModule/EmailRecoveryModuleBase.t.sol index 51aa3bef..c5494410 100644 --- a/test/integration/OwnableValidatorRecovery/EmailRecoveryModule/EmailRecoveryModuleBase.t.sol +++ b/test/integration/OwnableValidatorRecovery/EmailRecoveryModule/EmailRecoveryModuleBase.t.sol @@ -14,6 +14,7 @@ import { SubjectUtils } from "ether-email-auth/packages/contracts/src/libraries/ import { EmailRecoverySubjectHandler } from "src/handlers/EmailRecoverySubjectHandler.sol"; import { EmailRecoveryFactory } from "src/factories/EmailRecoveryFactory.sol"; import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; +import { EmailRecoveryModule } from "src/modules/EmailRecoveryModule.sol"; import { OwnableValidator } from "src/test/OwnableValidator.sol"; import { IntegrationBase } from "../../IntegrationBase.t.sol"; @@ -25,9 +26,8 @@ abstract contract OwnableValidatorRecovery_EmailRecoveryModule_Base is Integrati EmailRecoveryFactory emailRecoveryFactory; EmailRecoverySubjectHandler emailRecoveryHandler; - EmailRecoveryManager emailRecoveryManager; + EmailRecoveryModule emailRecoveryModule; - address emailRecoveryManagerAddress; address recoveryModuleAddress; address validatorAddress; @@ -57,20 +57,17 @@ abstract contract OwnableValidatorRecovery_EmailRecoveryModule_Base is Integrati // Deploy EmailRecoveryManager & EmailRecoveryModule bytes32 subjectHandlerSalt = bytes32(uint256(0)); - bytes32 recoveryManagerSalt = bytes32(uint256(0)); bytes32 recoveryModuleSalt = bytes32(uint256(0)); bytes memory subjectHandlerBytecode = type(EmailRecoverySubjectHandler).creationCode; - (recoveryModuleAddress, emailRecoveryManagerAddress,) = emailRecoveryFactory - .deployEmailRecoveryModule( + (recoveryModuleAddress,) = emailRecoveryFactory.deployEmailRecoveryModule( subjectHandlerSalt, - recoveryManagerSalt, recoveryModuleSalt, subjectHandlerBytecode, - address(ecdsaOwnedDkimRegistry), + address(dkimRegistry), validatorAddress, functionSelector ); - emailRecoveryManager = EmailRecoveryManager(emailRecoveryManagerAddress); + emailRecoveryModule = EmailRecoveryModule(recoveryModuleAddress); recoveryCalldata1 = abi.encodeWithSelector(functionSelector, newOwner1); recoveryCalldata2 = abi.encodeWithSelector(functionSelector, newOwner2); @@ -81,26 +78,17 @@ abstract contract OwnableValidatorRecovery_EmailRecoveryModule_Base is Integrati // Compute guardian addresses guardians1 = new address[](3); - guardians1[0] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt1); - guardians1[1] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt2); - guardians1[2] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt3); + guardians1[0] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt1); + guardians1[1] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt2); + guardians1[2] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt3); guardians2 = new address[](3); - guardians2[0] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt1); - guardians2[1] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt2); - guardians2[2] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt3); + guardians2[0] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt1); + guardians2[1] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt2); + guardians2[2] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt3); guardians3 = new address[](3); - guardians3[0] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt1); - guardians3[1] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt2); - guardians3[2] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt3); + guardians3[0] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt1); + guardians3[1] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt2); + guardians3[2] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt3); bytes memory recoveryModuleInstallData1 = abi.encode(isInstalledContext, guardians1, guardianWeights, threshold, delay, expiry); @@ -210,7 +198,7 @@ abstract contract OwnableValidatorRecovery_EmailRecoveryModule_Base is Integrati function acceptGuardian(address account, address guardian) public { EmailAuthMsg memory emailAuthMsg = getAcceptanceEmailAuthMessage(account, guardian); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function getAcceptanceEmailAuthMessage( @@ -230,7 +218,7 @@ abstract contract OwnableValidatorRecovery_EmailRecoveryModule_Base is Integrati bytes[] memory subjectParamsForAcceptance = new bytes[](1); subjectParamsForAcceptance[0] = abi.encode(account); return EmailAuthMsg({ - templateId: emailRecoveryManager.computeAcceptanceTemplateId(templateIdx), + templateId: emailRecoveryModule.computeAcceptanceTemplateId(templateIdx), subjectParams: subjectParamsForAcceptance, skipedSubjectPrefix: 0, proof: emailProof @@ -240,7 +228,7 @@ abstract contract OwnableValidatorRecovery_EmailRecoveryModule_Base is Integrati function handleRecovery(address account, address guardian, bytes32 calldataHash) public { EmailAuthMsg memory emailAuthMsg = getRecoveryEmailAuthMessage(account, guardian, calldataHash); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } function getRecoveryEmailAuthMessage( @@ -271,7 +259,7 @@ abstract contract OwnableValidatorRecovery_EmailRecoveryModule_Base is Integrati subjectParamsForRecovery[2] = abi.encode(calldataHashString); return EmailAuthMsg({ - templateId: emailRecoveryManager.computeRecoveryTemplateId(templateIdx), + templateId: emailRecoveryModule.computeRecoveryTemplateId(templateIdx), subjectParams: subjectParamsForRecovery, skipedSubjectPrefix: 0, proof: emailProof diff --git a/test/integration/OwnableValidatorRecovery/UniversalEmailRecoveryModule/UniversalEmailRecoveryModule.t.sol b/test/integration/OwnableValidatorRecovery/UniversalEmailRecoveryModule/UniversalEmailRecoveryModule.t.sol index dae7f502..3b28b76e 100644 --- a/test/integration/OwnableValidatorRecovery/UniversalEmailRecoveryModule/UniversalEmailRecoveryModule.t.sol +++ b/test/integration/OwnableValidatorRecovery/UniversalEmailRecoveryModule/UniversalEmailRecoveryModule.t.sol @@ -24,14 +24,14 @@ contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Integration_Test // Accept guardian 1 acceptGuardian(accountAddress1, guardians1[0]); GuardianStorage memory guardianStorage1 = - emailRecoveryManager.getGuardian(accountAddress1, guardians1[0]); + emailRecoveryModule.getGuardian(accountAddress1, guardians1[0]); assertEq(uint256(guardianStorage1.status), uint256(GuardianStatus.ACCEPTED)); assertEq(guardianStorage1.weight, uint256(1)); // Accept guardian 2 acceptGuardian(accountAddress1, guardians1[1]); GuardianStorage memory guardianStorage2 = - emailRecoveryManager.getGuardian(accountAddress1, guardians1[1]); + emailRecoveryModule.getGuardian(accountAddress1, guardians1[1]); assertEq(uint256(guardianStorage2.status), uint256(GuardianStatus.ACCEPTED)); assertEq(guardianStorage2.weight, uint256(2)); @@ -40,7 +40,7 @@ contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Integration_Test // handle recovery request for guardian 1 handleRecovery(accountAddress1, guardians1[0], calldataHash1); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress1); + emailRecoveryModule.getRecoveryRequest(accountAddress1); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 1); @@ -49,7 +49,7 @@ contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Integration_Test uint256 executeAfter = block.timestamp + delay; uint256 executeBefore = block.timestamp + expiry; handleRecovery(accountAddress1, guardians1[1], calldataHash1); - recoveryRequest = emailRecoveryManager.getRecoveryRequest(accountAddress1); + recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress1); assertEq(recoveryRequest.executeAfter, executeAfter); assertEq(recoveryRequest.executeBefore, executeBefore); assertEq(recoveryRequest.currentWeight, 3); @@ -58,9 +58,9 @@ contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Integration_Test vm.warp(block.timestamp + delay); // Complete recovery - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata1); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1); - recoveryRequest = emailRecoveryManager.getRecoveryRequest(accountAddress1); + recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress1); address updatedOwner = validator.owners(accountAddress1); assertEq(recoveryRequest.executeAfter, 0); @@ -88,7 +88,7 @@ contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Integration_Test // GuardianStatus.ACCEPTED // ) // ); - // emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + // emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); // } // function test_Recover_CannotMixAccountHandleRecovery() public { @@ -110,7 +110,7 @@ contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Integration_Test // GuardianStatus.ACCEPTED // ) // ); - // emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + // emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); // } // Helper function @@ -127,7 +127,7 @@ contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Integration_Test handleRecovery(account, guardians1[0], calldataHash); handleRecovery(account, guardians1[1], calldataHash); vm.warp(block.timestamp + delay); - emailRecoveryManager.completeRecovery(account, recoveryCalldata); + emailRecoveryModule.completeRecovery(account, recoveryCalldata); } // function test_Recover_RotatesMultipleOwnersSuccessfully() public { @@ -165,6 +165,6 @@ contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Integration_Test // ); // vm.expectRevert("invalid timestamp"); - // emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + // emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); // } } diff --git a/test/integration/OwnableValidatorRecovery/UniversalEmailRecoveryModule/UniversalEmailRecoveryModuleBase.t.sol b/test/integration/OwnableValidatorRecovery/UniversalEmailRecoveryModule/UniversalEmailRecoveryModuleBase.t.sol index e73c0bb4..63e49e52 100644 --- a/test/integration/OwnableValidatorRecovery/UniversalEmailRecoveryModule/UniversalEmailRecoveryModuleBase.t.sol +++ b/test/integration/OwnableValidatorRecovery/UniversalEmailRecoveryModule/UniversalEmailRecoveryModuleBase.t.sol @@ -15,6 +15,9 @@ import { EmailRecoverySubjectHandler } from "src/handlers/EmailRecoverySubjectHa import { EmailRecoveryFactory } from "src/factories/EmailRecoveryFactory.sol"; import { EmailRecoveryUniversalFactory } from "src/factories/EmailRecoveryUniversalFactory.sol"; import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; +import { UniversalEmailRecoveryModuleHarness } from + "../../../unit/UniversalEmailRecoveryModuleHarness.sol"; +// test/unit/UniversalEmailRecoveryModuleHarness.sol import { OwnableValidator } from "src/test/OwnableValidator.sol"; import { IntegrationBase } from "../../IntegrationBase.t.sol"; @@ -26,9 +29,8 @@ abstract contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Base is EmailRecoveryUniversalFactory emailRecoveryFactory; EmailRecoverySubjectHandler emailRecoveryHandler; - EmailRecoveryManager emailRecoveryManager; + UniversalEmailRecoveryModuleHarness emailRecoveryModule; - address emailRecoveryManagerAddress; address recoveryModuleAddress; address validatorAddress; @@ -53,18 +55,15 @@ abstract contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Base is // Deploy EmailRecoveryManager & UniversalEmailRecoveryModule bytes32 subjectHandlerSalt = bytes32(uint256(0)); - bytes32 recoveryManagerSalt = bytes32(uint256(0)); bytes32 recoveryModuleSalt = bytes32(uint256(0)); bytes memory subjectHandlerBytecode = type(EmailRecoverySubjectHandler).creationCode; - (recoveryModuleAddress, emailRecoveryManagerAddress,) = emailRecoveryFactory - .deployUniversalEmailRecoveryModule( - subjectHandlerSalt, - recoveryManagerSalt, - recoveryModuleSalt, - subjectHandlerBytecode, - address(ecdsaOwnedDkimRegistry) + emailRecoveryModule = new UniversalEmailRecoveryModuleHarness( + address(verifier), + address(dkimRegistry), + address(emailAuthImpl), + address(emailRecoveryHandler) ); - emailRecoveryManager = EmailRecoveryManager(emailRecoveryManagerAddress); + recoveryModuleAddress = address(emailRecoveryModule); // Deploy validator to be recovered validator = new OwnableValidator(); @@ -83,26 +82,17 @@ abstract contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Base is // Compute guardian addresses guardians1 = new address[](3); - guardians1[0] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt1); - guardians1[1] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt2); - guardians1[2] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt3); + guardians1[0] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt1); + guardians1[1] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt2); + guardians1[2] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt3); guardians2 = new address[](3); - guardians2[0] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt1); - guardians2[1] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt2); - guardians2[2] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt3); + guardians2[0] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt1); + guardians2[1] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt2); + guardians2[2] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt3); guardians3 = new address[](3); - guardians3[0] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt1); - guardians3[1] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt2); - guardians3[2] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt3); + guardians3[0] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt1); + guardians3[1] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt2); + guardians3[2] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt3); bytes memory recoveryModuleInstallData1 = abi.encode( validatorAddress, @@ -236,7 +226,7 @@ abstract contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Base is function acceptGuardian(address account, address guardian) public { EmailAuthMsg memory emailAuthMsg = getAcceptanceEmailAuthMessage(account, guardian); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function getAcceptanceEmailAuthMessage( @@ -256,7 +246,7 @@ abstract contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Base is bytes[] memory subjectParamsForAcceptance = new bytes[](1); subjectParamsForAcceptance[0] = abi.encode(account); return EmailAuthMsg({ - templateId: emailRecoveryManager.computeAcceptanceTemplateId(templateIdx), + templateId: emailRecoveryModule.computeAcceptanceTemplateId(templateIdx), subjectParams: subjectParamsForAcceptance, skipedSubjectPrefix: 0, proof: emailProof @@ -266,7 +256,7 @@ abstract contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Base is function handleRecovery(address account, address guardian, bytes32 calldataHash) public { EmailAuthMsg memory emailAuthMsg = getRecoveryEmailAuthMessage(account, guardian, calldataHash); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } function getRecoveryEmailAuthMessage( @@ -297,7 +287,7 @@ abstract contract OwnableValidatorRecovery_UniversalEmailRecoveryModule_Base is subjectParamsForRecovery[2] = abi.encode(calldataHashString); return EmailAuthMsg({ - templateId: emailRecoveryManager.computeRecoveryTemplateId(templateIdx), + templateId: emailRecoveryModule.computeRecoveryTemplateId(templateIdx), subjectParams: subjectParamsForRecovery, skipedSubjectPrefix: 0, proof: emailProof diff --git a/test/integration/SafeRecovery/SafeIntegrationBase.t.sol b/test/integration/SafeRecovery/SafeIntegrationBase.t.sol index b87c9b14..abc88e52 100644 --- a/test/integration/SafeRecovery/SafeIntegrationBase.t.sol +++ b/test/integration/SafeRecovery/SafeIntegrationBase.t.sol @@ -20,8 +20,7 @@ abstract contract SafeIntegrationBase is IntegrationBase { using Strings for address; SafeRecoverySubjectHandler safeRecoverySubjectHandler; - EmailRecoveryManager emailRecoveryManager; - address emailRecoveryManagerAddress; + UniversalEmailRecoveryModule emailRecoveryModule; address recoveryModuleAddress; bytes isInstalledContext; @@ -50,41 +49,30 @@ abstract contract SafeIntegrationBase is IntegrationBase { // Deploy handler, manager and module safeRecoverySubjectHandler = new SafeRecoverySubjectHandler(); - emailRecoveryManager = new EmailRecoveryManager( + emailRecoveryModule = new UniversalEmailRecoveryModule( address(verifier), - address(ecdsaOwnedDkimRegistry), + address(dkimRegistry), address(emailAuthImpl), address(safeRecoverySubjectHandler) ); - emailRecoveryManagerAddress = address(emailRecoveryManager); - - UniversalEmailRecoveryModule emailRecoveryModule = - new UniversalEmailRecoveryModule(emailRecoveryManagerAddress); recoveryModuleAddress = address(emailRecoveryModule); - emailRecoveryManager.initialize(recoveryModuleAddress); isInstalledContext = bytes("0"); functionSelector = bytes4(keccak256(bytes("swapOwner(address,address,address)"))); // Compute guardian addresses guardians1 = new address[](3); - guardians1[0] = emailRecoveryManager.computeEmailAuthAddress(accountAddress1, accountSalt1); - guardians1[1] = emailRecoveryManager.computeEmailAuthAddress(accountAddress1, accountSalt2); - guardians1[2] = emailRecoveryManager.computeEmailAuthAddress(accountAddress1, accountSalt3); + guardians1[0] = emailRecoveryModule.computeEmailAuthAddress(accountAddress1, accountSalt1); + guardians1[1] = emailRecoveryModule.computeEmailAuthAddress(accountAddress1, accountSalt2); + guardians1[2] = emailRecoveryModule.computeEmailAuthAddress(accountAddress1, accountSalt3); guardians2 = new address[](3); - guardians2[0] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt1); - guardians2[1] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt2); - guardians2[2] = - emailRecoveryManager.computeEmailAuthAddress(instance2.account, accountSalt3); + guardians2[0] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt1); + guardians2[1] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt2); + guardians2[2] = emailRecoveryModule.computeEmailAuthAddress(instance2.account, accountSalt3); guardians3 = new address[](3); - guardians3[0] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt1); - guardians3[1] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt2); - guardians3[2] = - emailRecoveryManager.computeEmailAuthAddress(instance3.account, accountSalt3); + guardians3[0] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt1); + guardians3[1] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt2); + guardians3[2] = emailRecoveryModule.computeEmailAuthAddress(instance3.account, accountSalt3); vm.prank(accountAddress1); instance1.installModule({ @@ -150,7 +138,7 @@ abstract contract SafeIntegrationBase is IntegrationBase { function acceptGuardian(address account, address guardian) public { EmailAuthMsg memory emailAuthMsg = getAcceptanceEmailAuthMessage(account, guardian); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function getAcceptanceEmailAuthMessage( @@ -170,7 +158,7 @@ abstract contract SafeIntegrationBase is IntegrationBase { bytes[] memory subjectParamsForAcceptance = new bytes[](1); subjectParamsForAcceptance[0] = abi.encode(account); return EmailAuthMsg({ - templateId: emailRecoveryManager.computeAcceptanceTemplateId(templateIdx), + templateId: emailRecoveryModule.computeAcceptanceTemplateId(templateIdx), subjectParams: subjectParamsForAcceptance, skipedSubjectPrefix: 0, proof: emailProof @@ -187,7 +175,7 @@ abstract contract SafeIntegrationBase is IntegrationBase { { EmailAuthMsg memory emailAuthMsg = getRecoveryEmailAuthMessage(account, oldOwner, newOwner, guardian); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } function getRecoveryEmailAuthMessage( @@ -227,7 +215,7 @@ abstract contract SafeIntegrationBase is IntegrationBase { subjectParamsForRecovery[3] = abi.encode(recoveryModuleAddress); return EmailAuthMsg({ - templateId: emailRecoveryManager.computeRecoveryTemplateId(templateIdx), + templateId: emailRecoveryModule.computeRecoveryTemplateId(templateIdx), subjectParams: subjectParamsForRecovery, skipedSubjectPrefix: 0, proof: emailProof diff --git a/test/integration/SafeRecovery/SafeRecovery.t.sol b/test/integration/SafeRecovery/SafeRecovery.t.sol index f3456d4d..712072d6 100644 --- a/test/integration/SafeRecovery/SafeRecovery.t.sol +++ b/test/integration/SafeRecovery/SafeRecovery.t.sol @@ -38,18 +38,18 @@ contract SafeRecovery_Integration_Test is SafeIntegrationBase { subjectParamsForRecovery[3] = abi.encode(recoveryModuleAddress); GuardianStorage memory guardianStorage1 = - emailRecoveryManager.getGuardian(accountAddress1, guardians1[0]); + emailRecoveryModule.getGuardian(accountAddress1, guardians1[0]); // Accept guardian acceptGuardian(accountAddress1, guardians1[0]); - guardianStorage1 = emailRecoveryManager.getGuardian(accountAddress1, guardians1[0]); + guardianStorage1 = emailRecoveryModule.getGuardian(accountAddress1, guardians1[0]); assertEq(uint256(guardianStorage1.status), uint256(GuardianStatus.ACCEPTED)); assertEq(guardianStorage1.weight, uint256(1)); // Accept guardian acceptGuardian(accountAddress1, guardians1[1]); GuardianStorage memory guardianStorage2 = - emailRecoveryManager.getGuardian(accountAddress1, guardians1[1]); + emailRecoveryModule.getGuardian(accountAddress1, guardians1[1]); assertEq(uint256(guardianStorage2.status), uint256(GuardianStatus.ACCEPTED)); assertEq(guardianStorage2.weight, uint256(2)); @@ -59,14 +59,14 @@ contract SafeRecovery_Integration_Test is SafeIntegrationBase { // handle recovery request for guardian 1 handleRecovery(accountAddress1, owner1, newOwner1, guardians1[0]); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress1); + emailRecoveryModule.getRecoveryRequest(accountAddress1); assertEq(recoveryRequest.currentWeight, 1); // handle recovery request for guardian 2 uint256 executeAfter = block.timestamp + delay; uint256 executeBefore = block.timestamp + expiry; handleRecovery(accountAddress1, owner1, newOwner1, guardians1[1]); - recoveryRequest = emailRecoveryManager.getRecoveryRequest(accountAddress1); + recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress1); assertEq(recoveryRequest.executeAfter, executeAfter); assertEq(recoveryRequest.executeBefore, executeBefore); assertEq(recoveryRequest.currentWeight, 3); @@ -74,9 +74,9 @@ contract SafeRecovery_Integration_Test is SafeIntegrationBase { vm.warp(block.timestamp + delay); // Complete recovery - emailRecoveryManager.completeRecovery(accountAddress1, recoveryCalldata); + emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata); - recoveryRequest = emailRecoveryManager.getRecoveryRequest(accountAddress1); + recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress1); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 0); @@ -94,7 +94,7 @@ contract SafeRecovery_Integration_Test is SafeIntegrationBase { // // configure and complete an entire recovery request // test_Recover_RotatesOwnerSuccessfully(); // address router = - // emailRecoveryManager.computeRouterAddress(keccak256(abi.encode(accountAddress1))); + // emailRecoveryModule.computeRouterAddress(keccak256(abi.encode(accountAddress1))); // IERC7579Account account = IERC7579Account(accountAddress1); // // Uninstall module @@ -111,14 +111,14 @@ contract SafeRecovery_Integration_Test is SafeIntegrationBase { // // assert that recovery config has been cleared successfully // IEmailRecoveryManager.RecoveryConfig memory recoveryConfig = - // emailRecoveryManager.getRecoveryConfig(accountAddress1); + // emailRecoveryModule.getRecoveryConfig(accountAddress1); // assertEq(recoveryConfig.recoveryModule, address(0)); // assertEq(recoveryConfig.delay, 0); // assertEq(recoveryConfig.expiry, 0); // // assert that the recovery request has been cleared successfully // IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - // emailRecoveryManager.getRecoveryRequest(accountAddress1); + // emailRecoveryModule.getRecoveryRequest(accountAddress1); // assertEq(recoveryRequest.executeAfter, 0); // assertEq(recoveryRequest.executeBefore, 0); // assertEq(recoveryRequest.currentWeight, 0); @@ -126,26 +126,26 @@ contract SafeRecovery_Integration_Test is SafeIntegrationBase { // // assert that guardian storage has been cleared successfully for guardian 1 // GuardianStorage memory guardianStorage1 = - // emailRecoveryManager.getGuardian(accountAddress1, guardians1[0]); + // emailRecoveryModule.getGuardian(accountAddress1, guardians1[0]); // assertEq(uint256(guardianStorage1.status), uint256(GuardianStatus.NONE)); // assertEq(guardianStorage1.weight, uint256(0)); // // assert that guardian storage has been cleared successfully for guardian 2 // GuardianStorage memory guardianStorage2 = - // emailRecoveryManager.getGuardian(accountAddress1, guardians1[1]); + // emailRecoveryModule.getGuardian(accountAddress1, guardians1[1]); // assertEq(uint256(guardianStorage2.status), uint256(GuardianStatus.NONE)); // assertEq(guardianStorage2.weight, uint256(0)); // // assert that guardian config has been cleared successfully - // IEmailRecoveryManager.GuardianConfig memory guardianConfig = - // emailRecoveryManager.getGuardianConfig(accountAddress1); + // GuardianManager.GuardianConfig memory guardianConfig = + // emailRecoveryModule.getGuardianConfig(accountAddress1); // assertEq(guardianConfig.guardianCount, 0); // assertEq(guardianConfig.totalWeight, 0); // assertEq(guardianConfig.threshold, 0); // // assert that the recovery router mappings have been cleared successfully - // address accountForRouter = emailRecoveryManager.getAccountForRouter(router); - // address routerForAccount = emailRecoveryManager.getRouterForAccount(accountAddress1); + // address accountForRouter = emailRecoveryModule.getAccountForRouter(router); + // address routerForAccount = emailRecoveryModule.getRouterForAccount(accountAddress1); // assertEq(accountForRouter, address(0)); // assertEq(routerForAccount, address(0)); // } diff --git a/test/unit/EmailRecoveryFactory/deployEmailRecoveryModule.t.sol b/test/unit/EmailRecoveryFactory/deployEmailRecoveryModule.t.sol index c4f5a3b5..bafa36a3 100644 --- a/test/unit/EmailRecoveryFactory/deployEmailRecoveryModule.t.sol +++ b/test/unit/EmailRecoveryFactory/deployEmailRecoveryModule.t.sol @@ -16,7 +16,6 @@ contract EmailRecoveryFactory_deployAll_Test is UnitBase { } function test_DeployEmailRecoveryModule_Succeeds() public { - bytes32 recoveryManagerSalt = bytes32(uint256(0)); bytes32 recoveryModuleSalt = bytes32(uint256(0)); bytes32 subjectHandlerSalt = bytes32(uint256(0)); @@ -25,39 +24,28 @@ contract EmailRecoveryFactory_deployAll_Test is UnitBase { subjectHandlerSalt, keccak256(subjectHandlerBytecode), address(emailRecoveryFactory) ); - bytes memory recoveryManagerBytecode = abi.encodePacked( - type(EmailRecoveryManager).creationCode, + bytes memory recoveryModuleBytecode = abi.encodePacked( + type(EmailRecoveryModule).creationCode, abi.encode( address(verifier), address(dkimRegistry), address(emailAuthImpl), - expectedSubjectHandler + expectedSubjectHandler, + validatorAddress, + functionSelector ) ); - address expectedManager = Create2.computeAddress( - recoveryManagerSalt, keccak256(recoveryManagerBytecode), address(emailRecoveryFactory) - ); - - bytes memory recoveryModuleBytecode = abi.encodePacked( - type(EmailRecoveryModule).creationCode, - abi.encode(expectedManager, validatorAddress, functionSelector) - ); address expectedModule = Create2.computeAddress( recoveryModuleSalt, keccak256(recoveryModuleBytecode), address(emailRecoveryFactory) ); vm.expectEmit(); emit EmailRecoveryFactory.EmailRecoveryModuleDeployed( - expectedModule, - expectedManager, - expectedSubjectHandler, - validatorAddress, - functionSelector + expectedModule, expectedSubjectHandler, validatorAddress, functionSelector ); - (address emailRecoveryModule, address emailRecoveryManager, address subjectHandler) = - emailRecoveryFactory.deployEmailRecoveryModule( + (address emailRecoveryModule, address subjectHandler) = emailRecoveryFactory + .deployEmailRecoveryModule( subjectHandlerSalt, - recoveryManagerSalt, recoveryModuleSalt, subjectHandlerBytecode, address(dkimRegistry), @@ -65,7 +53,6 @@ contract EmailRecoveryFactory_deployAll_Test is UnitBase { functionSelector ); - assertEq(emailRecoveryManager, expectedManager); assertEq(emailRecoveryModule, expectedModule); assertEq(subjectHandler, expectedSubjectHandler); } diff --git a/test/unit/EmailRecoveryManager/acceptGuardian.t.sol b/test/unit/EmailRecoveryManager/acceptGuardian.t.sol index 6008deab..a6d83360 100644 --- a/test/unit/EmailRecoveryManager/acceptGuardian.t.sol +++ b/test/unit/EmailRecoveryManager/acceptGuardian.t.sol @@ -5,6 +5,8 @@ import { console2 } from "forge-std/console2.sol"; import { ModuleKitHelpers, ModuleKitUserOp } from "modulekit/ModuleKit.sol"; import { MODULE_TYPE_EXECUTOR } from "modulekit/external/ERC7579.sol"; import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { GuardianManager } from "src/GuardianManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; import { UnitBase } from "../UnitBase.t.sol"; @@ -29,10 +31,8 @@ contract EmailRecoveryManager_acceptGuardian_Test is UnitBase { vm.warp(12 seconds); handleRecovery(recoveryModuleAddress, calldataHash, accountSalt1); - vm.expectRevert(IEmailRecoveryManager.RecoveryInProcess.selector); - emailRecoveryManager.exposed_acceptGuardian( - guardian1, templateIdx, subjectParams, nullifier - ); + vm.expectRevert(IGuardianManager.RecoveryInProcess.selector); + emailRecoveryModule.exposed_acceptGuardian(guardian1, templateIdx, subjectParams, nullifier); } function test_AcceptGuardian_RevertWhen_RecoveryModuleNotInstalled() public { @@ -40,10 +40,14 @@ contract EmailRecoveryManager_acceptGuardian_Test is UnitBase { instance.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, ""); vm.stopPrank(); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.exposed_acceptGuardian( - guardian1, templateIdx, subjectParams, nullifier + vm.expectRevert( + abi.encodeWithSelector( + IEmailRecoveryManager.InvalidGuardianStatus.selector, + uint256(GuardianStatus.NONE), + uint256(GuardianStatus.REQUESTED) + ) ); + emailRecoveryModule.exposed_acceptGuardian(guardian1, templateIdx, subjectParams, nullifier); } function test_AcceptGuardian_RevertWhen_GuardianStatusIsNONE() public { @@ -56,15 +60,13 @@ contract EmailRecoveryManager_acceptGuardian_Test is UnitBase { uint256(GuardianStatus.REQUESTED) ) ); - emailRecoveryManager.exposed_acceptGuardian( + emailRecoveryModule.exposed_acceptGuardian( invalidGuardian, templateIdx, subjectParams, nullifier ); } function test_AcceptGuardian_RevertWhen_GuardianStatusIsACCEPTED() public { - emailRecoveryManager.exposed_acceptGuardian( - guardian1, templateIdx, subjectParams, nullifier - ); + emailRecoveryModule.exposed_acceptGuardian(guardian1, templateIdx, subjectParams, nullifier); vm.expectRevert( abi.encodeWithSelector( @@ -73,25 +75,21 @@ contract EmailRecoveryManager_acceptGuardian_Test is UnitBase { uint256(GuardianStatus.REQUESTED) ) ); - emailRecoveryManager.exposed_acceptGuardian( - guardian1, templateIdx, subjectParams, nullifier - ); + emailRecoveryModule.exposed_acceptGuardian(guardian1, templateIdx, subjectParams, nullifier); } function test_AcceptGuardian_Succeeds() public { vm.expectEmit(); emit IEmailRecoveryManager.GuardianAccepted(accountAddress, guardian1); - emailRecoveryManager.exposed_acceptGuardian( - guardian1, templateIdx, subjectParams, nullifier - ); + emailRecoveryModule.exposed_acceptGuardian(guardian1, templateIdx, subjectParams, nullifier); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, guardian1); + emailRecoveryModule.getGuardian(accountAddress, guardian1); assertEq(uint256(guardianStorage.status), uint256(GuardianStatus.ACCEPTED)); assertEq(guardianStorage.weight, uint256(1)); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.acceptedWeight, guardianStorage.weight); } } diff --git a/test/unit/EmailRecoveryManager/acceptanceSubjectTemplates.t.sol b/test/unit/EmailRecoveryManager/acceptanceSubjectTemplates.t.sol index a718ccc3..a3115ee3 100644 --- a/test/unit/EmailRecoveryManager/acceptanceSubjectTemplates.t.sol +++ b/test/unit/EmailRecoveryManager/acceptanceSubjectTemplates.t.sol @@ -10,7 +10,7 @@ contract EmailRecoveryManager_acceptanceSubjectTemplates_Test is UnitBase { } function test_AcceptanceSubjectTemplates_Succeeds() public view { - string[][] memory templates = emailRecoveryManager.acceptanceSubjectTemplates(); + string[][] memory templates = emailRecoveryModule.acceptanceSubjectTemplates(); assertEq(templates.length, 1); assertEq(templates[0].length, 5); diff --git a/test/unit/EmailRecoveryManager/addGuardian.t.sol b/test/unit/EmailRecoveryManager/addGuardian.t.sol index 63ffc144..7fe4d64f 100644 --- a/test/unit/EmailRecoveryManager/addGuardian.t.sol +++ b/test/unit/EmailRecoveryManager/addGuardian.t.sol @@ -6,8 +6,9 @@ import { ModuleKitHelpers } from "modulekit/ModuleKit.sol"; import { MODULE_TYPE_EXECUTOR } from "modulekit/external/ERC7579.sol"; import { UnitBase } from "../UnitBase.t.sol"; import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { GuardianManager } from "src/GuardianManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; contract EmailRecoveryManager_addGuardian_Test is UnitBase { using ModuleKitHelpers for *; @@ -23,8 +24,8 @@ contract EmailRecoveryManager_addGuardian_Test is UnitBase { handleRecovery(recoveryModuleAddress, calldataHash, accountSalt1); vm.startPrank(accountAddress); - vm.expectRevert(IEmailRecoveryManager.RecoveryInProcess.selector); - emailRecoveryManager.addGuardian(guardians[0], guardianWeights[0]); + vm.expectRevert(IGuardianManager.RecoveryInProcess.selector); + emailRecoveryModule.addGuardian(guardians[0], guardianWeights[0]); } function test_AddGuardian_RevertWhen_SetupNotCalled() public { @@ -33,8 +34,8 @@ contract EmailRecoveryManager_addGuardian_Test is UnitBase { vm.stopPrank(); vm.startPrank(accountAddress); - vm.expectRevert(IEmailRecoveryManager.SetupNotCalled.selector); - emailRecoveryManager.addGuardian(guardians[0], guardianWeights[0]); + vm.expectRevert(IGuardianManager.SetupNotCalled.selector); + emailRecoveryModule.addGuardian(guardians[0], guardianWeights[0]); } function test_AddGuardian_AddGuardian_Succeeds() public { @@ -48,16 +49,16 @@ contract EmailRecoveryManager_addGuardian_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); - emit GuardianUtils.AddedGuardian(accountAddress, newGuardian, newGuardianWeight); - emailRecoveryManager.addGuardian(newGuardian, newGuardianWeight); + emit IGuardianManager.AddedGuardian(accountAddress, newGuardian, newGuardianWeight); // + emailRecoveryModule.addGuardian(newGuardian, newGuardianWeight); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, newGuardian); + emailRecoveryModule.getGuardian(accountAddress, newGuardian); assertEq(uint256(guardianStorage.status), uint256(GuardianStatus.REQUESTED)); assertEq(guardianStorage.weight, newGuardianWeight); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, expectedGuardianCount); assertEq(guardianConfig.totalWeight, expectedTotalWeight); assertEq(guardianConfig.acceptedWeight, expectedAcceptedWeight); diff --git a/test/unit/EmailRecoveryManager/cancelRecovery.t.sol b/test/unit/EmailRecoveryManager/cancelRecovery.t.sol index b7c4914f..feea26cd 100644 --- a/test/unit/EmailRecoveryManager/cancelRecovery.t.sol +++ b/test/unit/EmailRecoveryManager/cancelRecovery.t.sol @@ -16,7 +16,7 @@ contract EmailRecoveryManager_cancelRecovery_Test is UnitBase { function test_CancelRecovery_RevertWhen_NoRecoveryInProcess() public { vm.startPrank(accountAddress); vm.expectRevert(IEmailRecoveryManager.NoRecoveryInProcess.selector); - emailRecoveryManager.cancelRecovery(); + emailRecoveryModule.cancelRecovery(); } function test_CancelRecovery_CannotCancelWrongRecoveryRequest() public { @@ -28,7 +28,7 @@ contract EmailRecoveryManager_cancelRecovery_Test is UnitBase { handleRecovery(recoveryModuleAddress, calldataHash, accountSalt1); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 1); @@ -36,7 +36,7 @@ contract EmailRecoveryManager_cancelRecovery_Test is UnitBase { vm.startPrank(otherAddress); vm.expectRevert(IEmailRecoveryManager.NoRecoveryInProcess.selector); - emailRecoveryManager.cancelRecovery(); + emailRecoveryModule.cancelRecovery(); } function test_CancelRecovery_PartialRequest_Succeeds() public { @@ -46,16 +46,16 @@ contract EmailRecoveryManager_cancelRecovery_Test is UnitBase { handleRecovery(recoveryModuleAddress, calldataHash, accountSalt1); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 1); assertEq(recoveryRequest.calldataHash, ""); vm.startPrank(accountAddress); - emailRecoveryManager.cancelRecovery(); + emailRecoveryModule.cancelRecovery(); - recoveryRequest = emailRecoveryManager.getRecoveryRequest(accountAddress); + recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 0); @@ -70,7 +70,7 @@ contract EmailRecoveryManager_cancelRecovery_Test is UnitBase { handleRecovery(recoveryModuleAddress, calldataHash, accountSalt2); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, block.timestamp + delay); assertEq(recoveryRequest.executeBefore, block.timestamp + expiry); assertEq(recoveryRequest.currentWeight, 3); @@ -79,9 +79,9 @@ contract EmailRecoveryManager_cancelRecovery_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); emit IEmailRecoveryManager.RecoveryCancelled(accountAddress); - emailRecoveryManager.cancelRecovery(); + emailRecoveryModule.cancelRecovery(); - recoveryRequest = emailRecoveryManager.getRecoveryRequest(accountAddress); + recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 0); diff --git a/test/unit/EmailRecoveryManager/changeThreshold.t.sol b/test/unit/EmailRecoveryManager/changeThreshold.t.sol index efa9cc35..9caec9f0 100644 --- a/test/unit/EmailRecoveryManager/changeThreshold.t.sol +++ b/test/unit/EmailRecoveryManager/changeThreshold.t.sol @@ -3,8 +3,7 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; contract EmailRecoveryManager_changeThreshold_Test is UnitBase { function setUp() public override { @@ -18,8 +17,8 @@ contract EmailRecoveryManager_changeThreshold_Test is UnitBase { handleRecovery(recoveryModuleAddress, calldataHash, accountSalt1); vm.startPrank(accountAddress); - vm.expectRevert(IEmailRecoveryManager.RecoveryInProcess.selector); - emailRecoveryManager.changeThreshold(threshold); + vm.expectRevert(IGuardianManager.RecoveryInProcess.selector); + emailRecoveryModule.changeThreshold(threshold); } function test_ChangeThreshold_IncreaseThreshold() public { @@ -27,11 +26,11 @@ contract EmailRecoveryManager_changeThreshold_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); - emit GuardianUtils.ChangedThreshold(accountAddress, newThreshold); - emailRecoveryManager.changeThreshold(newThreshold); + emit IGuardianManager.ChangedThreshold(accountAddress, newThreshold); + emailRecoveryModule.changeThreshold(newThreshold); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, guardians.length); assertEq(guardianConfig.threshold, newThreshold); } @@ -41,11 +40,11 @@ contract EmailRecoveryManager_changeThreshold_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); - emit GuardianUtils.ChangedThreshold(accountAddress, newThreshold); - emailRecoveryManager.changeThreshold(newThreshold); + emit IGuardianManager.ChangedThreshold(accountAddress, newThreshold); + emailRecoveryModule.changeThreshold(newThreshold); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, guardians.length); assertEq(guardianConfig.threshold, newThreshold); } diff --git a/test/unit/EmailRecoveryManager/completeRecovery.t.sol b/test/unit/EmailRecoveryManager/completeRecovery.t.sol index 7b7df166..42e8c99f 100644 --- a/test/unit/EmailRecoveryManager/completeRecovery.t.sol +++ b/test/unit/EmailRecoveryManager/completeRecovery.t.sol @@ -14,7 +14,7 @@ contract EmailRecoveryManager_completeRecovery_Test is UnitBase { address invalidAccount = address(0); vm.expectRevert(IEmailRecoveryManager.InvalidAccountAddress.selector); - emailRecoveryManager.completeRecovery(invalidAccount, recoveryCalldata); + emailRecoveryModule.completeRecovery(invalidAccount, recoveryCalldata); } function test_CompleteRecovery_RevertWhen_NotEnoughApprovals() public { @@ -29,7 +29,7 @@ contract EmailRecoveryManager_completeRecovery_Test is UnitBase { IEmailRecoveryManager.NotEnoughApprovals.selector, guardianWeights[0], threshold ) ); - emailRecoveryManager.completeRecovery(accountAddress, recoveryCalldata); + emailRecoveryModule.completeRecovery(accountAddress, recoveryCalldata); } function test_CompleteRecovery_RevertWhen_DelayNotPassed() public { @@ -49,7 +49,7 @@ contract EmailRecoveryManager_completeRecovery_Test is UnitBase { block.timestamp + delay ) ); - emailRecoveryManager.completeRecovery(accountAddress, recoveryCalldata); + emailRecoveryModule.completeRecovery(accountAddress, recoveryCalldata); } function test_CompleteRecovery_RevertWhen_RecoveryRequestExpiredAndTimestampEqualToExpiry() @@ -70,7 +70,7 @@ contract EmailRecoveryManager_completeRecovery_Test is UnitBase { IEmailRecoveryManager.RecoveryRequestExpired.selector, block.timestamp, executeAfter ) ); - emailRecoveryManager.completeRecovery(accountAddress, recoveryCalldata); + emailRecoveryModule.completeRecovery(accountAddress, recoveryCalldata); } function test_CompleteRecovery_RevertWhen_RecoveryRequestExpiredAndTimestampMoreThanExpiry() @@ -91,7 +91,7 @@ contract EmailRecoveryManager_completeRecovery_Test is UnitBase { IEmailRecoveryManager.RecoveryRequestExpired.selector, block.timestamp, executeAfter ) ); - emailRecoveryManager.completeRecovery(accountAddress, recoveryCalldata); + emailRecoveryModule.completeRecovery(accountAddress, recoveryCalldata); } function test_CompleteRecovery_RevertWhen_InvalidCalldataHash() public { @@ -112,7 +112,7 @@ contract EmailRecoveryManager_completeRecovery_Test is UnitBase { calldataHash ) ); - emailRecoveryManager.completeRecovery(accountAddress, invalidRecoveryCalldata); + emailRecoveryModule.completeRecovery(accountAddress, invalidRecoveryCalldata); } function test_CompleteRecovery_Succeeds() public { @@ -126,10 +126,10 @@ contract EmailRecoveryManager_completeRecovery_Test is UnitBase { vm.expectEmit(); emit IEmailRecoveryManager.RecoveryCompleted(accountAddress); - emailRecoveryManager.completeRecovery(accountAddress, recoveryCalldata); + emailRecoveryModule.completeRecovery(accountAddress, recoveryCalldata); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 0); @@ -147,10 +147,10 @@ contract EmailRecoveryManager_completeRecovery_Test is UnitBase { vm.expectEmit(); emit IEmailRecoveryManager.RecoveryCompleted(accountAddress); - emailRecoveryManager.completeRecovery(accountAddress, recoveryCalldata); + emailRecoveryModule.completeRecovery(accountAddress, recoveryCalldata); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 0); diff --git a/test/unit/EmailRecoveryManager/configureRecovery.t.sol b/test/unit/EmailRecoveryManager/configureRecovery.t.sol index 40ad02a5..db423c3e 100644 --- a/test/unit/EmailRecoveryManager/configureRecovery.t.sol +++ b/test/unit/EmailRecoveryManager/configureRecovery.t.sol @@ -6,7 +6,7 @@ import { ModuleKitHelpers } from "modulekit/ModuleKit.sol"; import { MODULE_TYPE_EXECUTOR } from "modulekit/external/ERC7579.sol"; import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { UnitBase } from "../UnitBase.t.sol"; contract EmailRecoveryManager_configureRecovery_Test is UnitBase { @@ -24,23 +24,17 @@ contract EmailRecoveryManager_configureRecovery_Test is UnitBase { vm.expectRevert(IEmailRecoveryManager.SetupAlreadyCalled.selector); vm.startPrank(accountAddress); - emailRecoveryManager.configureRecovery(guardians, guardianWeights, threshold, delay, expiry); + emailRecoveryModule.exposed_configureRecovery( + guardians, guardianWeights, threshold, delay, expiry + ); } function test_ConfigureRecovery_RevertWhen_ConfigureRecoveryCalledTwice() public { vm.startPrank(accountAddress); vm.expectRevert(IEmailRecoveryManager.SetupAlreadyCalled.selector); - emailRecoveryManager.configureRecovery(guardians, guardianWeights, threshold, delay, expiry); - } - - function test_ConfigureRecovery_RevertWhen_RecoveryModuleNotInstalled() public { - vm.prank(accountAddress); - instance.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, ""); - vm.stopPrank(); - - vm.prank(accountAddress); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.configureRecovery(guardians, guardianWeights, threshold, delay, expiry); + emailRecoveryModule.exposed_configureRecovery( + guardians, guardianWeights, threshold, delay, expiry + ); } function test_ConfigureRecovery_Succeeds() public { @@ -52,22 +46,24 @@ contract EmailRecoveryManager_configureRecovery_Test is UnitBase { emit IEmailRecoveryManager.RecoveryConfigured( instance.account, guardians.length, totalWeight, threshold ); - emailRecoveryManager.configureRecovery(guardians, guardianWeights, threshold, delay, expiry); + emailRecoveryModule.exposed_configureRecovery( + guardians, guardianWeights, threshold, delay, expiry + ); IEmailRecoveryManager.RecoveryConfig memory recoveryConfig = - emailRecoveryManager.getRecoveryConfig(accountAddress); + emailRecoveryModule.getRecoveryConfig(accountAddress); assertEq(recoveryConfig.delay, delay); assertEq(recoveryConfig.expiry, expiry); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, guardians.length); assertEq(guardianConfig.totalWeight, totalWeight); assertEq(guardianConfig.acceptedWeight, 0); // no guardians accepted yet assertEq(guardianConfig.threshold, threshold); GuardianStorage memory guardian = - emailRecoveryManager.getGuardian(accountAddress, guardians[0]); + emailRecoveryModule.getGuardian(accountAddress, guardians[0]); assertEq(uint256(guardian.status), uint256(GuardianStatus.REQUESTED)); assertEq(guardian.weight, guardianWeights[0]); } @@ -80,12 +76,12 @@ contract EmailRecoveryManager_configureRecovery_Test is UnitBase { vm.expectRevert( abi.encodeWithSelector( - GuardianUtils.IncorrectNumberOfWeights.selector, + IGuardianManager.IncorrectNumberOfWeights.selector, zeroGuardians.length, guardianWeights.length ) ); - emailRecoveryManager.configureRecovery( + emailRecoveryModule.exposed_configureRecovery( zeroGuardians, guardianWeights, threshold, delay, expiry ); } @@ -98,12 +94,12 @@ contract EmailRecoveryManager_configureRecovery_Test is UnitBase { vm.expectRevert( abi.encodeWithSelector( - GuardianUtils.IncorrectNumberOfWeights.selector, + IGuardianManager.IncorrectNumberOfWeights.selector, guardians.length, zeroGuardianWeights.length ) ); - emailRecoveryManager.configureRecovery( + emailRecoveryModule.exposed_configureRecovery( guardians, zeroGuardianWeights, threshold, delay, expiry ); } @@ -114,8 +110,8 @@ contract EmailRecoveryManager_configureRecovery_Test is UnitBase { emailRecoveryModule.workaround_validatorsPush(accountAddress, validatorAddress); uint256 zeroThreshold = 0; - vm.expectRevert(GuardianUtils.ThresholdCannotBeZero.selector); - emailRecoveryManager.configureRecovery( + vm.expectRevert(IGuardianManager.ThresholdCannotBeZero.selector); + emailRecoveryModule.exposed_configureRecovery( guardians, guardianWeights, zeroThreshold, delay, expiry ); } @@ -129,9 +125,11 @@ contract EmailRecoveryManager_configureRecovery_Test is UnitBase { uint256[] memory zeroGuardianWeights; vm.expectRevert( - abi.encodeWithSelector(GuardianUtils.ThresholdExceedsTotalWeight.selector, threshold, 0) + abi.encodeWithSelector( + IGuardianManager.ThresholdExceedsTotalWeight.selector, threshold, 0 + ) ); - emailRecoveryManager.configureRecovery( + emailRecoveryModule.exposed_configureRecovery( zeroGuardians, zeroGuardianWeights, threshold, delay, expiry ); } diff --git a/test/unit/EmailRecoveryManager/constructor.t.sol b/test/unit/EmailRecoveryManager/constructor.t.sol index d1eae6cb..b47f1247 100644 --- a/test/unit/EmailRecoveryManager/constructor.t.sol +++ b/test/unit/EmailRecoveryManager/constructor.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../UnitBase.t.sol"; import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; -import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; +import { UniversalEmailRecoveryModule } from "src/modules/UniversalEmailRecoveryModule.sol"; contract EmailRecoveryManager_constructor_Test is UnitBase { function setUp() public override { @@ -14,7 +14,7 @@ contract EmailRecoveryManager_constructor_Test is UnitBase { function test_Constructor_RevertWhen_InvalidVerifier() public { address invalidVerifier = address(0); vm.expectRevert(IEmailRecoveryManager.InvalidVerifier.selector); - new EmailRecoveryManager( + new UniversalEmailRecoveryModule( invalidVerifier, address(dkimRegistry), address(emailAuthImpl), @@ -25,7 +25,7 @@ contract EmailRecoveryManager_constructor_Test is UnitBase { function test_Constructor_RevertWhen_InvalidDkimRegistry() public { address invalidDkim = address(0); vm.expectRevert(IEmailRecoveryManager.InvalidDkimRegistry.selector); - new EmailRecoveryManager( + new UniversalEmailRecoveryModule( address(verifier), invalidDkim, address(emailAuthImpl), address(emailRecoveryHandler) ); } @@ -33,7 +33,7 @@ contract EmailRecoveryManager_constructor_Test is UnitBase { function test_Constructor_RevertWhen_InvalidEmailAuthImpl() public { address invalidEmailAuth = address(0); vm.expectRevert(IEmailRecoveryManager.InvalidEmailAuthImpl.selector); - new EmailRecoveryManager( + new UniversalEmailRecoveryModule( address(verifier), address(dkimRegistry), invalidEmailAuth, @@ -44,22 +44,22 @@ contract EmailRecoveryManager_constructor_Test is UnitBase { function test_Constructor_RevertWhen_InvalidSubjectHandler() public { address invalidHandler = address(0); vm.expectRevert(IEmailRecoveryManager.InvalidSubjectHandler.selector); - new EmailRecoveryManager( + new UniversalEmailRecoveryModule( address(verifier), address(dkimRegistry), address(emailAuthImpl), invalidHandler ); } function test_Constructor() public { - EmailRecoveryManager emailRecoveryManager = new EmailRecoveryManager( + UniversalEmailRecoveryModule emailRecoveryModule = new UniversalEmailRecoveryModule( address(verifier), address(dkimRegistry), address(emailAuthImpl), address(emailRecoveryHandler) ); - assertEq(address(verifier), emailRecoveryManager.verifier()); - assertEq(address(dkimRegistry), emailRecoveryManager.dkim()); - assertEq(address(emailAuthImpl), emailRecoveryManager.emailAuthImplementation()); - assertEq(address(emailRecoveryHandler), emailRecoveryManager.subjectHandler()); + assertEq(address(verifier), emailRecoveryModule.verifier()); + assertEq(address(dkimRegistry), emailRecoveryModule.dkim()); + assertEq(address(emailAuthImpl), emailRecoveryModule.emailAuthImplementation()); + assertEq(address(emailRecoveryHandler), emailRecoveryModule.subjectHandler()); } } diff --git a/test/unit/EmailRecoveryManager/deInitRecoveryFromModule.t.sol b/test/unit/EmailRecoveryManager/deInitRecoveryModule.t.sol similarity index 67% rename from test/unit/EmailRecoveryManager/deInitRecoveryFromModule.t.sol rename to test/unit/EmailRecoveryManager/deInitRecoveryModule.t.sol index 76f2cd43..1a11735b 100644 --- a/test/unit/EmailRecoveryManager/deInitRecoveryFromModule.t.sol +++ b/test/unit/EmailRecoveryManager/deInitRecoveryModule.t.sol @@ -4,47 +4,44 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../UnitBase.t.sol"; import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { GuardianManager } from "src/GuardianManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -contract EmailRecoveryManager_deInitRecoveryFromModule_Test is UnitBase { +contract EmailRecoveryManager_deInitRecoveryModule_Test is UnitBase { function setUp() public override { super.setUp(); } - function test_DeInitRecoveryFromModule_RevertWhen_NotCalledFromRecoveryModule() public { - vm.expectRevert(IEmailRecoveryManager.NotRecoveryModule.selector); - emailRecoveryManager.deInitRecoveryFromModule(accountAddress); - } - - function test_DeInitRecoveryFromModule_RevertWhen_RecoveryInProcess() public { + function test_DeInitRecoveryModule_RevertWhen_RecoveryInProcess() public { acceptGuardian(accountSalt1); acceptGuardian(accountSalt2); vm.warp(12 seconds); handleRecovery(recoveryModuleAddress, calldataHash, accountSalt1); vm.prank(recoveryModuleAddress); - vm.expectRevert(IEmailRecoveryManager.RecoveryInProcess.selector); - emailRecoveryManager.deInitRecoveryFromModule(accountAddress); + vm.expectRevert(IGuardianManager.RecoveryInProcess.selector); + emailRecoveryModule.exposed_deInitRecoveryModule(accountAddress); } - function test_DeInitRecoveryFromModule_Succeeds() public { + function test_DeInitRecoveryModule_Succeeds() public { acceptGuardian(accountSalt1); acceptGuardian(accountSalt2); vm.prank(recoveryModuleAddress); vm.expectEmit(); emit IEmailRecoveryManager.RecoveryDeInitialized(accountAddress); - emailRecoveryManager.deInitRecoveryFromModule(accountAddress); + emailRecoveryModule.exposed_deInitRecoveryModule(accountAddress); // assert that recovery config has been cleared successfully IEmailRecoveryManager.RecoveryConfig memory recoveryConfig = - emailRecoveryManager.getRecoveryConfig(accountAddress); + emailRecoveryModule.getRecoveryConfig(accountAddress); assertEq(recoveryConfig.delay, 0); assertEq(recoveryConfig.expiry, 0); // assert that the recovery request has been cleared successfully IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 0); @@ -52,19 +49,19 @@ contract EmailRecoveryManager_deInitRecoveryFromModule_Test is UnitBase { // assert that guardian storage has been cleared successfully for guardian 1 GuardianStorage memory guardianStorage1 = - emailRecoveryManager.getGuardian(accountAddress, guardian1); + emailRecoveryModule.getGuardian(accountAddress, guardian1); assertEq(uint256(guardianStorage1.status), uint256(GuardianStatus.NONE)); assertEq(guardianStorage1.weight, uint256(0)); // assert that guardian storage has been cleared successfully for guardian 2 GuardianStorage memory guardianStorage2 = - emailRecoveryManager.getGuardian(accountAddress, guardian2); + emailRecoveryModule.getGuardian(accountAddress, guardian2); assertEq(uint256(guardianStorage2.status), uint256(GuardianStatus.NONE)); assertEq(guardianStorage2.weight, uint256(0)); // assert that guardian config has been cleared successfully - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + GuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, 0); assertEq(guardianConfig.totalWeight, 0); assertEq(guardianConfig.acceptedWeight, 0); diff --git a/test/unit/EmailRecoveryManager/getGuardian.t.sol b/test/unit/EmailRecoveryManager/getGuardian.t.sol index 2b377c2f..031772e6 100644 --- a/test/unit/EmailRecoveryManager/getGuardian.t.sol +++ b/test/unit/EmailRecoveryManager/getGuardian.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; import { UnitBase } from "../UnitBase.t.sol"; @@ -14,13 +13,13 @@ contract EmailRecoveryManager_getGuardian_Test is UnitBase { super.setUp(); vm.startPrank(accountAddress); - emailRecoveryManager.addGuardian(newGuardian, newGuardianWeight); + emailRecoveryModule.addGuardian(newGuardian, newGuardianWeight); vm.stopPrank(); } function test_GetGuardian_Succeeds() public { GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, newGuardian); + emailRecoveryModule.getGuardian(accountAddress, newGuardian); assertEq(uint256(guardianStorage.status), uint256(GuardianStatus.REQUESTED)); assertEq(guardianStorage.weight, newGuardianWeight); } diff --git a/test/unit/EmailRecoveryManager/getGuardianConfig.t.sol b/test/unit/EmailRecoveryManager/getGuardianConfig.t.sol index ff74a33f..d54ce60c 100644 --- a/test/unit/EmailRecoveryManager/getGuardianConfig.t.sol +++ b/test/unit/EmailRecoveryManager/getGuardianConfig.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; import { UnitBase } from "../UnitBase.t.sol"; @@ -24,13 +24,13 @@ contract EmailRecoveryManager_getGuardianConfig_Test is UnitBase { expectedThreshold = threshold; vm.startPrank(accountAddress); - emailRecoveryManager.addGuardian(newGuardian, newGuardianWeight); + emailRecoveryModule.addGuardian(newGuardian, newGuardianWeight); vm.stopPrank(); } function test_GetGuardianConfig_Succeeds() public { - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, expectedGuardianCount); assertEq(guardianConfig.totalWeight, expectedTotalWeight); assertEq(guardianConfig.acceptedWeight, expectedAcceptedWeight); diff --git a/test/unit/EmailRecoveryManager/getRecoveryConfig.t.sol b/test/unit/EmailRecoveryManager/getRecoveryConfig.t.sol index 38d8ae85..77a13d29 100644 --- a/test/unit/EmailRecoveryManager/getRecoveryConfig.t.sol +++ b/test/unit/EmailRecoveryManager/getRecoveryConfig.t.sol @@ -17,16 +17,16 @@ contract EmailRecoveryManager_getRecoveryConfig_Test is UnitBase { IEmailRecoveryManager.RecoveryConfig(newDelay, newExpiry); vm.startPrank(accountAddress); - emailRecoveryManager.updateRecoveryConfig(recoveryConfig); + emailRecoveryModule.updateRecoveryConfig(recoveryConfig); - recoveryConfig = emailRecoveryManager.getRecoveryConfig(accountAddress); + recoveryConfig = emailRecoveryModule.getRecoveryConfig(accountAddress); assertEq(recoveryConfig.delay, newDelay); assertEq(recoveryConfig.expiry, newExpiry); } function test_GetRecoveryConfig_Succeeds() public { IEmailRecoveryManager.RecoveryConfig memory result = - emailRecoveryManager.getRecoveryConfig(accountAddress); + emailRecoveryModule.getRecoveryConfig(accountAddress); assertEq(result.delay, newDelay); assertEq(result.expiry, newExpiry); } diff --git a/test/unit/EmailRecoveryManager/getRecoveryRequest.t.sol b/test/unit/EmailRecoveryManager/getRecoveryRequest.t.sol index 6c594afd..d76f6ea6 100644 --- a/test/unit/EmailRecoveryManager/getRecoveryRequest.t.sol +++ b/test/unit/EmailRecoveryManager/getRecoveryRequest.t.sol @@ -18,7 +18,7 @@ contract EmailRecoveryManager_getRecoveryRequest_Test is UnitBase { handleRecovery(recoveryModuleAddress, calldataHash, accountSalt1); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, 1); diff --git a/test/unit/EmailRecoveryManager/initialize.t.sol b/test/unit/EmailRecoveryManager/initialize.t.sol deleted file mode 100644 index d8cfd365..00000000 --- a/test/unit/EmailRecoveryManager/initialize.t.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import { console2 } from "forge-std/console2.sol"; -import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; -import { UnitBase } from "../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; -import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; - -contract EmailRecoveryManager_initialize_Test is UnitBase { - EmailRecoveryManager manager; - - function setUp() public override { - super.setUp(); - - vm.startPrank(accountAddress); - manager = new EmailRecoveryManager( - address(verifier), - address(dkimRegistry), - address(emailAuthImpl), - address(emailRecoveryHandler) - ); - vm.stopPrank(); - } - - function test_Initialize_RevertWhen_InitializerNotDeployer() public { - vm.expectRevert(IEmailRecoveryManager.InitializerNotDeployer.selector); - manager.initialize(recoveryModuleAddress); - } - - function test_Initialize_RevertWhen_InvalidRecoveryModule() public { - address invalidRecoveryModule = address(0); - - vm.startPrank(accountAddress); - vm.expectRevert(IEmailRecoveryManager.InvalidRecoveryModule.selector); - manager.initialize(invalidRecoveryModule); - } - - function test_Initialize_RevertWhen_CalledMoreThanOnce() public { - vm.startPrank(accountAddress); - manager.initialize(recoveryModuleAddress); - - vm.expectRevert(Initializable.InvalidInitialization.selector); - manager.initialize(recoveryModuleAddress); - } - - function test_Initialize_Succeeds() public { - vm.startPrank(accountAddress); - manager.initialize(recoveryModuleAddress); - - assertEq(manager.emailRecoveryModule(), recoveryModuleAddress); - } -} diff --git a/test/unit/EmailRecoveryManager/processRecovery.t.sol b/test/unit/EmailRecoveryManager/processRecovery.t.sol index aeab9c76..a01d7f4f 100644 --- a/test/unit/EmailRecoveryManager/processRecovery.t.sol +++ b/test/unit/EmailRecoveryManager/processRecovery.t.sol @@ -43,7 +43,7 @@ contract EmailRecoveryManager_processRecovery_Test is UnitBase { uint256(GuardianStatus.ACCEPTED) ) ); - emailRecoveryManager.exposed_processRecovery( + emailRecoveryModule.exposed_processRecovery( invalidGuardian, templateIdx, subjectParams, nullifier ); } @@ -61,7 +61,7 @@ contract EmailRecoveryManager_processRecovery_Test is UnitBase { uint256(GuardianStatus.ACCEPTED) ) ); - emailRecoveryManager.exposed_processRecovery( + emailRecoveryModule.exposed_processRecovery( guardian1, templateIdx, subjectParams, nullifier ); } @@ -71,8 +71,14 @@ contract EmailRecoveryManager_processRecovery_Test is UnitBase { instance.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, ""); vm.stopPrank(); - vm.expectRevert(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector); - emailRecoveryManager.exposed_processRecovery( + vm.expectRevert( + abi.encodeWithSelector( + IEmailRecoveryManager.InvalidGuardianStatus.selector, + uint256(GuardianStatus.NONE), + uint256(GuardianStatus.ACCEPTED) + ) + ); + emailRecoveryModule.exposed_processRecovery( guardian1, templateIdx, subjectParams, nullifier ); } @@ -94,8 +100,8 @@ contract EmailRecoveryManager_processRecovery_Test is UnitBase { uint256 newThreshold = 5; vm.startPrank(accountAddress); - emailRecoveryManager.addGuardian(newGuardian, newWeight); - emailRecoveryManager.changeThreshold(newThreshold); + emailRecoveryModule.addGuardian(newGuardian, newWeight); + emailRecoveryModule.changeThreshold(newThreshold); vm.stopPrank(); // total weight = 5 // threshold = 5 @@ -108,7 +114,7 @@ contract EmailRecoveryManager_processRecovery_Test is UnitBase { IEmailRecoveryManager.ThresholdExceedsAcceptedWeight.selector, newThreshold, 3 ) ); - emailRecoveryManager.exposed_processRecovery( + emailRecoveryModule.exposed_processRecovery( guardian2, templateIdx, subjectParams, nullifier ); } @@ -119,12 +125,12 @@ contract EmailRecoveryManager_processRecovery_Test is UnitBase { acceptGuardian(accountSalt1); acceptGuardian(accountSalt2); - emailRecoveryManager.exposed_processRecovery( + emailRecoveryModule.exposed_processRecovery( guardian1, templateIdx, subjectParams, nullifier ); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, 0); assertEq(recoveryRequest.executeBefore, 0); assertEq(recoveryRequest.currentWeight, guardian1Weight); @@ -150,12 +156,12 @@ contract EmailRecoveryManager_processRecovery_Test is UnitBase { block.timestamp + expiry, calldataHash ); - emailRecoveryManager.exposed_processRecovery( + emailRecoveryModule.exposed_processRecovery( guardian2, templateIdx, subjectParams, nullifier ); IEmailRecoveryManager.RecoveryRequest memory recoveryRequest = - emailRecoveryManager.getRecoveryRequest(accountAddress); + emailRecoveryModule.getRecoveryRequest(accountAddress); assertEq(recoveryRequest.executeAfter, block.timestamp + delay); assertEq(recoveryRequest.executeBefore, block.timestamp + expiry); assertEq(recoveryRequest.currentWeight, guardian1Weight + guardian2Weight); diff --git a/test/unit/EmailRecoveryManager/recoverySubjectTemplates.t.sol b/test/unit/EmailRecoveryManager/recoverySubjectTemplates.t.sol index 6ea3bbc4..b6446af3 100644 --- a/test/unit/EmailRecoveryManager/recoverySubjectTemplates.t.sol +++ b/test/unit/EmailRecoveryManager/recoverySubjectTemplates.t.sol @@ -10,7 +10,7 @@ contract EmailRecoveryManager_recoverySubjectTemplates_Test is UnitBase { } function test_RecoverySubjectTemplates_Succeeds() public view { - string[][] memory templates = emailRecoveryManager.recoverySubjectTemplates(); + string[][] memory templates = emailRecoveryModule.recoverySubjectTemplates(); assertEq(templates.length, 1); assertEq(templates[0].length, 11); diff --git a/test/unit/EmailRecoveryManager/removeGuardian.t.sol b/test/unit/EmailRecoveryManager/removeGuardian.t.sol index 23e623b6..0f80cf57 100644 --- a/test/unit/EmailRecoveryManager/removeGuardian.t.sol +++ b/test/unit/EmailRecoveryManager/removeGuardian.t.sol @@ -4,9 +4,8 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; contract EmailRecoveryManager_removeGuardian_Test is UnitBase { function setUp() public override { @@ -22,8 +21,8 @@ contract EmailRecoveryManager_removeGuardian_Test is UnitBase { handleRecovery(recoveryModuleAddress, calldataHash, accountSalt1); vm.startPrank(accountAddress); - vm.expectRevert(IEmailRecoveryManager.RecoveryInProcess.selector); - emailRecoveryManager.removeGuardian(guardian); + vm.expectRevert(IGuardianManager.RecoveryInProcess.selector); + emailRecoveryModule.removeGuardian(guardian); } function test_RemoveGuardian_Succeeds() public { @@ -40,16 +39,16 @@ contract EmailRecoveryManager_removeGuardian_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); - emit GuardianUtils.RemovedGuardian(accountAddress, guardian, guardianWeights[0]); - emailRecoveryManager.removeGuardian(guardian); + emit IGuardianManager.RemovedGuardian(accountAddress, guardian, guardianWeights[0]); + emailRecoveryModule.removeGuardian(guardian); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, guardian); + emailRecoveryModule.getGuardian(accountAddress, guardian); assertEq(uint256(guardianStorage.status), uint256(GuardianStatus.NONE)); assertEq(guardianStorage.weight, 0); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, guardians.length - 1); assertEq(guardianConfig.totalWeight, totalWeight - guardianWeights[0]); assertEq(guardianConfig.acceptedWeight, 0); // 1 - 1 = 0 diff --git a/test/unit/EmailRecoveryManager/setupGuardians.t.sol b/test/unit/EmailRecoveryManager/setupGuardians.t.sol index 6be11993..cf8be14b 100644 --- a/test/unit/EmailRecoveryManager/setupGuardians.t.sol +++ b/test/unit/EmailRecoveryManager/setupGuardians.t.sol @@ -5,7 +5,7 @@ import { console2 } from "forge-std/console2.sol"; import { ModuleKitHelpers } from "modulekit/ModuleKit.sol"; import { MODULE_TYPE_EXECUTOR } from "modulekit/external/ERC7579.sol"; import { UnitBase } from "../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; contract EmailRecoveryManager_setupGuardians_Test is UnitBase { @@ -24,16 +24,16 @@ contract EmailRecoveryManager_setupGuardians_Test is UnitBase { instance.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, ""); vm.stopPrank(); - (uint256 guardianCount, uint256 totalWeight) = emailRecoveryManager.exposed_setupGuardians( + (uint256 guardianCount, uint256 totalWeight) = emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, guardianWeights, threshold ); GuardianStorage memory guardianStorage1 = - emailRecoveryManager.getGuardian(accountAddress, guardians[0]); + emailRecoveryModule.getGuardian(accountAddress, guardians[0]); GuardianStorage memory guardianStorage2 = - emailRecoveryManager.getGuardian(accountAddress, guardians[1]); + emailRecoveryModule.getGuardian(accountAddress, guardians[1]); GuardianStorage memory guardianStorage3 = - emailRecoveryManager.getGuardian(accountAddress, guardians[2]); + emailRecoveryModule.getGuardian(accountAddress, guardians[2]); assertEq(uint256(guardianStorage1.status), uint256(GuardianStatus.REQUESTED)); assertEq(guardianStorage1.weight, guardianWeights[0]); assertEq(uint256(guardianStorage2.status), uint256(GuardianStatus.REQUESTED)); @@ -44,8 +44,8 @@ contract EmailRecoveryManager_setupGuardians_Test is UnitBase { assertEq(guardianCount, expectedGuardianCount); assertEq(totalWeight, expectedTotalWeight); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, expectedGuardianCount); assertEq(guardianConfig.totalWeight, expectedTotalWeight); assertEq(guardianConfig.acceptedWeight, 0); // no guardians accepted diff --git a/test/unit/EmailRecoveryManager/updateRecoveryConfig.t.sol b/test/unit/EmailRecoveryManager/updateRecoveryConfig.t.sol index eb09f01b..ea7658da 100644 --- a/test/unit/EmailRecoveryManager/updateRecoveryConfig.t.sol +++ b/test/unit/EmailRecoveryManager/updateRecoveryConfig.t.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../UnitBase.t.sol"; import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; contract EmailRecoveryManager_updateRecoveryConfig_Test is UnitBase { function setUp() public override { @@ -21,8 +22,8 @@ contract EmailRecoveryManager_updateRecoveryConfig_Test is UnitBase { handleRecovery(recoveryModuleAddress, calldataHash, accountSalt2); vm.startPrank(accountAddress); - vm.expectRevert(IEmailRecoveryManager.RecoveryInProcess.selector); - emailRecoveryManager.updateRecoveryConfig(recoveryConfig); + vm.expectRevert(IGuardianManager.RecoveryInProcess.selector); + emailRecoveryModule.updateRecoveryConfig(recoveryConfig); } function test_UpdateRecoveryConfig_RevertWhen_AccountNotConfigured() public { @@ -32,7 +33,7 @@ contract EmailRecoveryManager_updateRecoveryConfig_Test is UnitBase { vm.startPrank(nonConfiguredAccount); vm.expectRevert(IEmailRecoveryManager.AccountNotConfigured.selector); - emailRecoveryManager.updateRecoveryConfig(recoveryConfig); + emailRecoveryModule.updateRecoveryConfig(recoveryConfig); } function test_UpdateRecoveryConfig_RevertWhen_DelayMoreThanExpiry() public { @@ -47,7 +48,7 @@ contract EmailRecoveryManager_updateRecoveryConfig_Test is UnitBase { IEmailRecoveryManager.DelayMoreThanExpiry.selector, invalidDelay, expiry ) ); - emailRecoveryManager.updateRecoveryConfig(recoveryConfig); + emailRecoveryModule.updateRecoveryConfig(recoveryConfig); } function test_UpdateRecoveryConfig_RevertWhen_RecoveryWindowTooShort() public { @@ -63,7 +64,7 @@ contract EmailRecoveryManager_updateRecoveryConfig_Test is UnitBase { IEmailRecoveryManager.RecoveryWindowTooShort.selector, newExpiry - newDelay ) ); - emailRecoveryManager.updateRecoveryConfig(recoveryConfig); + emailRecoveryModule.updateRecoveryConfig(recoveryConfig); } function test_UpdateRecoveryConfig_RevertWhen_RecoveryWindowTooShortByOneSecond() public { @@ -79,7 +80,7 @@ contract EmailRecoveryManager_updateRecoveryConfig_Test is UnitBase { IEmailRecoveryManager.RecoveryWindowTooShort.selector, newExpiry - newDelay ) ); - emailRecoveryManager.updateRecoveryConfig(recoveryConfig); + emailRecoveryModule.updateRecoveryConfig(recoveryConfig); } function test_UpdateRecoveryConfig_SucceedsWhenRecoveryWindowEqualsMinimumRecoveryWindow() @@ -92,9 +93,9 @@ contract EmailRecoveryManager_updateRecoveryConfig_Test is UnitBase { IEmailRecoveryManager.RecoveryConfig(newDelay, newExpiry); vm.startPrank(accountAddress); - emailRecoveryManager.updateRecoveryConfig(recoveryConfig); + emailRecoveryModule.updateRecoveryConfig(recoveryConfig); - recoveryConfig = emailRecoveryManager.getRecoveryConfig(accountAddress); + recoveryConfig = emailRecoveryModule.getRecoveryConfig(accountAddress); assertEq(recoveryConfig.delay, newDelay); assertEq(recoveryConfig.expiry, newExpiry); } @@ -111,9 +112,9 @@ contract EmailRecoveryManager_updateRecoveryConfig_Test is UnitBase { emit IEmailRecoveryManager.RecoveryConfigUpdated( accountAddress, recoveryConfig.delay, recoveryConfig.expiry ); - emailRecoveryManager.updateRecoveryConfig(recoveryConfig); + emailRecoveryModule.updateRecoveryConfig(recoveryConfig); - recoveryConfig = emailRecoveryManager.getRecoveryConfig(accountAddress); + recoveryConfig = emailRecoveryModule.getRecoveryConfig(accountAddress); assertEq(recoveryConfig.delay, newDelay); assertEq(recoveryConfig.expiry, newExpiry); } diff --git a/test/unit/EmailRecoveryManagerHarness.sol b/test/unit/EmailRecoveryManagerHarness.sol deleted file mode 100644 index 1d8b3dcb..00000000 --- a/test/unit/EmailRecoveryManagerHarness.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import { console2 } from "forge-std/console2.sol"; -import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; -import { EnumerableGuardianMap, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; - -contract EmailRecoveryManagerHarness is EmailRecoveryManager { - using GuardianUtils for mapping(address => EnumerableGuardianMap.AddressToGuardianMap); - - constructor( - address verifier, - address dkimRegistry, - address emailAuthImpl, - address subjectHandler - ) - EmailRecoveryManager(verifier, dkimRegistry, emailAuthImpl, subjectHandler) - { } - - function exposed_acceptGuardian( - address guardian, - uint256 templateIdx, - bytes[] memory subjectParams, - bytes32 nullifier - ) - external - { - acceptGuardian(guardian, templateIdx, subjectParams, nullifier); - } - - function exposed_processRecovery( - address guardian, - uint256 templateIdx, - bytes[] memory subjectParams, - bytes32 nullifier - ) - external - { - processRecovery(guardian, templateIdx, subjectParams, nullifier); - } - - function exposed_setupGuardians( - address account, - address[] calldata guardians, - uint256[] calldata weights, - uint256 threshold - ) - external - returns (uint256, uint256) - { - return setupGuardians(account, guardians, weights, threshold); - } - - function exposed_updateGuardianStatus( - address account, - address guardian, - GuardianStatus newStatus - ) - external - { - guardiansStorage.updateGuardianStatus(account, guardian, newStatus); - } - - function exposed_removeAllGuardians(address account) external { - guardiansStorage.removeAllGuardians(account); - } -} diff --git a/test/unit/EmailRecoveryModuleHarness.sol b/test/unit/EmailRecoveryModuleHarness.sol new file mode 100644 index 00000000..a3f3729f --- /dev/null +++ b/test/unit/EmailRecoveryModuleHarness.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { console2 } from "forge-std/console2.sol"; +import { SentinelListLib } from "sentinellist/SentinelList.sol"; +import { EnumerableGuardianMap, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; +import { EmailRecoveryModule } from "src/modules/EmailRecoveryModule.sol"; + +contract EmailRecoveryModuleHarness is EmailRecoveryModule { + using SentinelListLib for SentinelListLib.SentinelList; + + constructor( + address verifier, + address dkimRegistry, + address emailAuthImpl, + address subjectHandler, + address validator, + bytes4 selector + ) + EmailRecoveryModule(verifier, dkimRegistry, emailAuthImpl, subjectHandler, validator, selector) + { } + + function exposed_recover(address account, bytes calldata recoveryCalldata) external { + recover(account, recoveryCalldata); + } +} diff --git a/test/unit/EmailRecoveryUniversalFactory/deployUniversalEmailRecoveryModule.t.sol b/test/unit/EmailRecoveryUniversalFactory/deployUniversalEmailRecoveryModule.t.sol index 27e259d5..38aa29b4 100644 --- a/test/unit/EmailRecoveryUniversalFactory/deployUniversalEmailRecoveryModule.t.sol +++ b/test/unit/EmailRecoveryUniversalFactory/deployUniversalEmailRecoveryModule.t.sol @@ -7,7 +7,6 @@ import { UnitBase } from "../UnitBase.t.sol"; import { EmailRecoveryFactory } from "src/factories/EmailRecoveryFactory.sol"; import { EmailRecoveryUniversalFactory } from "src/factories/EmailRecoveryUniversalFactory.sol"; import { EmailRecoverySubjectHandler } from "src/handlers/EmailRecoverySubjectHandler.sol"; -import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; import { UniversalEmailRecoveryModule } from "src/modules/UniversalEmailRecoveryModule.sol"; contract EmailRecoveryUniversalFactory_deployUniversalEmailRecoveryModule_Test is UnitBase { @@ -16,7 +15,6 @@ contract EmailRecoveryUniversalFactory_deployUniversalEmailRecoveryModule_Test i } function test_DeployUniversalEmailRecoveryModule_Succeeds() public { - bytes32 recoveryManagerSalt = bytes32(uint256(0)); bytes32 recoveryModuleSalt = bytes32(uint256(0)); bytes32 subjectHandlerSalt = bytes32(uint256(0)); @@ -27,8 +25,8 @@ contract EmailRecoveryUniversalFactory_deployUniversalEmailRecoveryModule_Test i address(emailRecoveryUniversalFactory) ); - bytes memory recoveryManagerBytecode = abi.encodePacked( - type(EmailRecoveryManager).creationCode, + bytes memory recoveryModuleBytecode = abi.encodePacked( + type(UniversalEmailRecoveryModule).creationCode, abi.encode( address(verifier), address(dkimRegistry), @@ -36,15 +34,6 @@ contract EmailRecoveryUniversalFactory_deployUniversalEmailRecoveryModule_Test i expectedSubjectHandler ) ); - address expectedManager = Create2.computeAddress( - recoveryManagerSalt, - keccak256(recoveryManagerBytecode), - address(emailRecoveryUniversalFactory) - ); - - bytes memory recoveryModuleBytecode = abi.encodePacked( - type(UniversalEmailRecoveryModule).creationCode, abi.encode(expectedManager) - ); address expectedModule = Create2.computeAddress( recoveryModuleSalt, keccak256(recoveryModuleBytecode), @@ -53,18 +42,13 @@ contract EmailRecoveryUniversalFactory_deployUniversalEmailRecoveryModule_Test i vm.expectEmit(); emit EmailRecoveryUniversalFactory.UniversalEmailRecoveryModuleDeployed( - expectedModule, expectedManager, expectedSubjectHandler + expectedModule, expectedSubjectHandler ); - (address emailRecoveryModule, address emailRecoveryManager, address subjectHandler) = - emailRecoveryUniversalFactory.deployUniversalEmailRecoveryModule( - subjectHandlerSalt, - recoveryManagerSalt, - recoveryModuleSalt, - subjectHandlerBytecode, - address(dkimRegistry) + (address emailRecoveryModule, address subjectHandler) = emailRecoveryUniversalFactory + .deployUniversalEmailRecoveryModule( + subjectHandlerSalt, recoveryModuleSalt, subjectHandlerBytecode, address(dkimRegistry) ); - assertEq(emailRecoveryManager, expectedManager); assertEq(emailRecoveryModule, expectedModule); assertEq(subjectHandler, expectedSubjectHandler); } diff --git a/test/unit/SafeUnitBase.t.sol b/test/unit/SafeUnitBase.t.sol index 39ba89ee..2e3e6f81 100644 --- a/test/unit/SafeUnitBase.t.sol +++ b/test/unit/SafeUnitBase.t.sol @@ -8,7 +8,6 @@ import { EmailAuthMsg, EmailProof } from "ether-email-auth/packages/contracts/sr import { SubjectUtils } from "ether-email-auth/packages/contracts/src/libraries/SubjectUtils.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { EmailRecoveryManagerHarness } from "./EmailRecoveryManagerHarness.sol"; import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; import { UniversalEmailRecoveryModule } from "src/modules/UniversalEmailRecoveryModule.sol"; import { SafeRecoverySubjectHandlerHarness } from "./SafeRecoverySubjectHandlerHarness.sol"; @@ -21,8 +20,7 @@ abstract contract SafeUnitBase is IntegrationBase { EmailRecoveryFactory emailRecoveryFactory; SafeRecoverySubjectHandlerHarness safeRecoverySubjectHandler; - EmailRecoveryManager emailRecoveryManager; - address emailRecoveryManagerAddress; + UniversalEmailRecoveryModule emailRecoveryModule; address recoveryModuleAddress; bytes4 functionSelector; @@ -60,18 +58,13 @@ abstract contract SafeUnitBase is IntegrationBase { safeRecoverySubjectHandler = new SafeRecoverySubjectHandlerHarness(); emailRecoveryFactory = new EmailRecoveryFactory(address(verifier), address(emailAuthImpl)); - emailRecoveryManager = new EmailRecoveryManagerHarness( + emailRecoveryModule = new UniversalEmailRecoveryModule( address(verifier), - address(ecdsaOwnedDkimRegistry), + address(dkimRegistry), address(emailAuthImpl), address(safeRecoverySubjectHandler) ); - emailRecoveryManagerAddress = address(emailRecoveryManager); - - UniversalEmailRecoveryModule emailRecoveryModule = - new UniversalEmailRecoveryModule(emailRecoveryManagerAddress); recoveryModuleAddress = address(emailRecoveryModule); - emailRecoveryManager.initialize(recoveryModuleAddress); functionSelector = bytes4(keccak256(bytes("swapOwner(address,address,address)"))); address previousOwnerInLinkedList = address(1); @@ -86,12 +79,9 @@ abstract contract SafeUnitBase is IntegrationBase { // Compute guardian addresses guardians1 = new address[](3); - guardians1[0] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt1); - guardians1[1] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt2); - guardians1[2] = - emailRecoveryManager.computeEmailAuthAddress(instance1.account, accountSalt3); + guardians1[0] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt1); + guardians1[1] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt2); + guardians1[2] = emailRecoveryModule.computeEmailAuthAddress(instance1.account, accountSalt3); instance1.installModule({ moduleTypeId: MODULE_TYPE_EXECUTOR, @@ -147,12 +137,12 @@ abstract contract SafeUnitBase is IntegrationBase { subjectParamsForAcceptance[0] = abi.encode(account); EmailAuthMsg memory emailAuthMsg = EmailAuthMsg({ - templateId: emailRecoveryManager.computeAcceptanceTemplateId(templateIdx), + templateId: emailRecoveryModule.computeAcceptanceTemplateId(templateIdx), subjectParams: subjectParamsForAcceptance, skipedSubjectPrefix: 0, proof: emailProof }); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function handleRecovery(address account, bytes32 accountSalt) public { @@ -176,11 +166,11 @@ abstract contract SafeUnitBase is IntegrationBase { subjectParamsForRecovery[2] = abi.encode(calldataHashString); EmailAuthMsg memory emailAuthMsg = EmailAuthMsg({ - templateId: emailRecoveryManager.computeRecoveryTemplateId(templateIdx), + templateId: emailRecoveryModule.computeRecoveryTemplateId(templateIdx), subjectParams: subjectParamsForRecovery, skipedSubjectPrefix: 0, proof: emailProof }); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } } diff --git a/test/unit/UnitBase.t.sol b/test/unit/UnitBase.t.sol index 1b76829a..fa189d12 100644 --- a/test/unit/UnitBase.t.sol +++ b/test/unit/UnitBase.t.sol @@ -21,7 +21,6 @@ import { import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { ECDSA } from "solady/utils/ECDSA.sol"; -import { EmailRecoveryManagerHarness } from "./EmailRecoveryManagerHarness.sol"; import { EmailRecoverySubjectHandler } from "src/handlers/EmailRecoverySubjectHandler.sol"; import { UniversalEmailRecoveryModuleHarness } from "./UniversalEmailRecoveryModuleHarness.sol"; import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; @@ -44,11 +43,8 @@ abstract contract UnitBase is RhinestoneModuleKit, Test { EmailRecoveryFactory emailRecoveryFactory; EmailRecoveryUniversalFactory emailRecoveryUniversalFactory; EmailRecoverySubjectHandler emailRecoveryHandler; - EmailRecoveryManagerHarness emailRecoveryManager; UniversalEmailRecoveryModuleHarness emailRecoveryModule; - // EmailRecoveryManager emailRecoveryManager; - address emailRecoveryManagerAddress; address recoveryModuleAddress; address validatorAddress; @@ -115,17 +111,13 @@ abstract contract UnitBase is RhinestoneModuleKit, Test { emailRecoveryUniversalFactory = new EmailRecoveryUniversalFactory(address(verifier), address(emailAuthImpl)); - emailRecoveryManager = new EmailRecoveryManagerHarness( + emailRecoveryModule = new UniversalEmailRecoveryModuleHarness( address(verifier), address(dkimRegistry), address(emailAuthImpl), address(emailRecoveryHandler) ); - emailRecoveryManagerAddress = address(emailRecoveryManager); - - emailRecoveryModule = new UniversalEmailRecoveryModuleHarness(emailRecoveryManagerAddress); recoveryModuleAddress = address(emailRecoveryModule); - emailRecoveryManager.initialize(recoveryModuleAddress); // Deploy and fund the account instance = makeAccountInstance("account"); @@ -137,9 +129,9 @@ abstract contract UnitBase is RhinestoneModuleKit, Test { accountSalt3 = keccak256(abi.encode("account salt 3")); // Compute guardian addresses - guardian1 = emailRecoveryManager.computeEmailAuthAddress(instance.account, accountSalt1); - guardian2 = emailRecoveryManager.computeEmailAuthAddress(instance.account, accountSalt2); - guardian3 = emailRecoveryManager.computeEmailAuthAddress(instance.account, accountSalt3); + guardian1 = emailRecoveryModule.computeEmailAuthAddress(instance.account, accountSalt1); + guardian2 = emailRecoveryModule.computeEmailAuthAddress(instance.account, accountSalt2); + guardian3 = emailRecoveryModule.computeEmailAuthAddress(instance.account, accountSalt3); guardians = new address[](3); guardians[0] = guardian1; @@ -255,13 +247,13 @@ abstract contract UnitBase is RhinestoneModuleKit, Test { bytes[] memory subjectParamsForAcceptance = new bytes[](1); subjectParamsForAcceptance[0] = abi.encode(accountAddress); EmailAuthMsg memory emailAuthMsg = EmailAuthMsg({ - templateId: emailRecoveryManager.computeAcceptanceTemplateId(templateIdx), + templateId: emailRecoveryModule.computeAcceptanceTemplateId(templateIdx), subjectParams: subjectParamsForAcceptance, skipedSubjectPrefix: 0, proof: emailProof }); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function handleRecovery( @@ -289,11 +281,11 @@ abstract contract UnitBase is RhinestoneModuleKit, Test { subjectParamsForRecovery[2] = abi.encode(calldataHashString); EmailAuthMsg memory emailAuthMsg = EmailAuthMsg({ - templateId: emailRecoveryManager.computeRecoveryTemplateId(templateIdx), + templateId: emailRecoveryModule.computeRecoveryTemplateId(templateIdx), subjectParams: subjectParamsForRecovery, skipedSubjectPrefix: 0, proof: emailProof }); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } } diff --git a/test/unit/UniversalEmailRecoveryModuleHarness.sol b/test/unit/UniversalEmailRecoveryModuleHarness.sol index 1836537b..017f9a23 100644 --- a/test/unit/UniversalEmailRecoveryModuleHarness.sol +++ b/test/unit/UniversalEmailRecoveryModuleHarness.sol @@ -3,12 +3,88 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { SentinelListLib } from "sentinellist/SentinelList.sol"; +import { EnumerableGuardianMap, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; import { UniversalEmailRecoveryModule } from "src/modules/UniversalEmailRecoveryModule.sol"; contract UniversalEmailRecoveryModuleHarness is UniversalEmailRecoveryModule { using SentinelListLib for SentinelListLib.SentinelList; - constructor(address emailRecoveryManager) UniversalEmailRecoveryModule(emailRecoveryManager) { } + constructor( + address verifier, + address dkimRegistry, + address emailAuthImpl, + address subjectHandler + ) + UniversalEmailRecoveryModule(verifier, dkimRegistry, emailAuthImpl, subjectHandler) + { } + + function exposed_configureRecovery( + address[] memory guardians, + uint256[] memory weights, + uint256 threshold, + uint256 delay, + uint256 expiry + ) + external + { + configureRecovery(guardians, weights, threshold, delay, expiry); + } + + function exposed_acceptGuardian( + address guardian, + uint256 templateIdx, + bytes[] memory subjectParams, + bytes32 nullifier + ) + external + { + acceptGuardian(guardian, templateIdx, subjectParams, nullifier); + } + + function exposed_processRecovery( + address guardian, + uint256 templateIdx, + bytes[] memory subjectParams, + bytes32 nullifier + ) + external + { + processRecovery(guardian, templateIdx, subjectParams, nullifier); + } + + function exposed_recover(address account, bytes calldata recoveryCalldata) external { + recover(account, recoveryCalldata); + } + + function exposed_deInitRecoveryModule(address account) external { + deInitRecoveryModule(account); + } + + function exposed_setupGuardians( + address account, + address[] calldata guardians, + uint256[] calldata weights, + uint256 threshold + ) + external + returns (uint256, uint256) + { + return setupGuardians(account, guardians, weights, threshold); + } + + function exposed_updateGuardianStatus( + address account, + address guardian, + GuardianStatus newStatus + ) + external + { + updateGuardianStatus(account, guardian, newStatus); + } + + function exposed_removeAllGuardians(address account) external { + removeAllGuardians(account); + } function workaround_validatorsPush(address account, address validator) external { validators[account].push(validator); diff --git a/test/unit/assertErrorSelectors.t.sol b/test/unit/assertErrorSelectors.t.sol index 6934269e..569ade74 100644 --- a/test/unit/assertErrorSelectors.t.sol +++ b/test/unit/assertErrorSelectors.t.sol @@ -6,12 +6,13 @@ import { console2 } from "forge-std/console2.sol"; import { EmailRecoverySubjectHandler } from "src/handlers/EmailRecoverySubjectHandler.sol"; import { SafeRecoverySubjectHandler } from "src/handlers/SafeRecoverySubjectHandler.sol"; import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { GuardianManager } from "src/GuardianManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { EmailRecoveryUniversalFactory } from "src/factories/EmailRecoveryUniversalFactory.sol"; import { EmailRecoveryFactory } from "src/factories/EmailRecoveryFactory.sol"; import { EmailRecoveryModule } from "src/modules/EmailRecoveryModule.sol"; import { UniversalEmailRecoveryModule } from "src/modules/UniversalEmailRecoveryModule.sol"; import { EnumerableGuardianMap } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; // Helper test to associate custom error bytes with error names. Could just write the selector bytes // in the contracts but this method reduces human error from copying values and also when updating @@ -39,10 +40,9 @@ contract LogErrorSelectors_Test is Test { assertEq(IEmailRecoveryManager.InvalidSubjectHandler.selector, bytes4(0x436dcac5)); assertEq(IEmailRecoveryManager.InitializerNotDeployer.selector, bytes4(0x3b141fc4)); assertEq(IEmailRecoveryManager.InvalidRecoveryModule.selector, bytes4(0x7f263111)); - assertEq(IEmailRecoveryManager.RecoveryInProcess.selector, bytes4(0xf90ea6fc)); + assertEq(IGuardianManager.RecoveryInProcess.selector, bytes4(0xf90ea6fc)); assertEq(IEmailRecoveryManager.SetupAlreadyCalled.selector, bytes4(0xb3af5593)); assertEq(IEmailRecoveryManager.AccountNotConfigured.selector, bytes4(0x66ecbd6d)); - assertEq(IEmailRecoveryManager.RecoveryModuleNotAuthorized.selector, bytes4(0xbfa7d2a9)); assertEq(IEmailRecoveryManager.DelayMoreThanExpiry.selector, bytes4(0xb742a43c)); assertEq(IEmailRecoveryManager.RecoveryWindowTooShort.selector, bytes4(0x50799cce)); assertEq(IEmailRecoveryManager.ThresholdExceedsAcceptedWeight.selector, bytes4(0x7c3e983c)); @@ -54,8 +54,6 @@ contract LogErrorSelectors_Test is Test { assertEq(IEmailRecoveryManager.RecoveryRequestExpired.selector, bytes4(0x566ad75e)); assertEq(IEmailRecoveryManager.InvalidCalldataHash.selector, bytes4(0x54d53855)); assertEq(IEmailRecoveryManager.NoRecoveryInProcess.selector, bytes4(0x87434f51)); - assertEq(IEmailRecoveryManager.NotRecoveryModule.selector, bytes4(0x2f6ef3d6)); - assertEq(IEmailRecoveryManager.SetupNotCalled.selector, bytes4(0xae69115b)); } function test_EmailRecoveryUniversalFactory_AssertSelectors() public { @@ -70,15 +68,12 @@ contract LogErrorSelectors_Test is Test { function test_EmailRecoveryModule_AssertSelectors() public { assertEq(EmailRecoveryModule.InvalidSelector.selector, bytes4(0x12ba286f)); - assertEq(EmailRecoveryModule.InvalidManager.selector, bytes4(0x34e70f7a)); assertEq(EmailRecoveryModule.InvalidOnInstallData.selector, bytes4(0x5c223882)); assertEq(EmailRecoveryModule.InvalidValidator.selector, bytes4(0x11d5c560)); - assertEq(EmailRecoveryModule.NotTrustedRecoveryManager.selector, bytes4(0x38f1b648)); assertEq(EmailRecoveryModule.RecoveryNotAuthorizedForAccount.selector, bytes4(0xba14d9ef)); } function test_UniversalEmailRecoveryModule_AssertSelectors() public { - assertEq(UniversalEmailRecoveryModule.InvalidManager.selector, bytes4(0x34e70f7a)); assertEq(UniversalEmailRecoveryModule.InvalidSelector.selector, bytes4(0x12ba286f)); assertEq( UniversalEmailRecoveryModule.RecoveryModuleNotInitialized.selector, bytes4(0x0b088c23) @@ -86,9 +81,6 @@ contract LogErrorSelectors_Test is Test { assertEq(UniversalEmailRecoveryModule.InvalidOnInstallData.selector, bytes4(0x5c223882)); assertEq(UniversalEmailRecoveryModule.InvalidValidator.selector, bytes4(0x11d5c560)); assertEq(UniversalEmailRecoveryModule.MaxValidatorsReached.selector, bytes4(0xed7948d6)); - assertEq( - UniversalEmailRecoveryModule.NotTrustedRecoveryManager.selector, bytes4(0x38f1b648) - ); } function test_EnumerableGuardianMap_AssertSelectors() public { @@ -96,15 +88,15 @@ contract LogErrorSelectors_Test is Test { assertEq(EnumerableGuardianMap.TooManyValuesToRemove.selector, bytes4(0xe023c211)); } - function test_GuardianUtils_AssertSelectors() public { - assertEq(GuardianUtils.IncorrectNumberOfWeights.selector, bytes4(0x166e79bd)); - assertEq(GuardianUtils.ThresholdCannotBeZero.selector, bytes4(0xf4124166)); - assertEq(GuardianUtils.InvalidGuardianAddress.selector, bytes4(0x1af74975)); - assertEq(GuardianUtils.InvalidGuardianWeight.selector, bytes4(0x148f78e0)); - assertEq(GuardianUtils.AddressAlreadyGuardian.selector, bytes4(0xe4e1614e)); - assertEq(GuardianUtils.ThresholdExceedsTotalWeight.selector, bytes4(0xeb912f71)); - assertEq(GuardianUtils.StatusCannotBeTheSame.selector, bytes4(0x7e120711)); - assertEq(GuardianUtils.SetupNotCalled.selector, bytes4(0xae69115b)); - assertEq(GuardianUtils.AddressNotGuardianForAccount.selector, bytes4(0xf3f77749)); + function test_IGuardianManager_AssertSelectors() public { + assertEq(IGuardianManager.IncorrectNumberOfWeights.selector, bytes4(0x166e79bd)); + assertEq(IGuardianManager.ThresholdCannotBeZero.selector, bytes4(0xf4124166)); + assertEq(IGuardianManager.InvalidGuardianAddress.selector, bytes4(0x1af74975)); + assertEq(IGuardianManager.InvalidGuardianWeight.selector, bytes4(0x148f78e0)); + assertEq(IGuardianManager.AddressAlreadyGuardian.selector, bytes4(0xe4e1614e)); + assertEq(IGuardianManager.ThresholdExceedsTotalWeight.selector, bytes4(0xeb912f71)); + assertEq(IGuardianManager.StatusCannotBeTheSame.selector, bytes4(0x7e120711)); + assertEq(IGuardianManager.SetupNotCalled.selector, bytes4(0xae69115b)); + assertEq(IGuardianManager.AddressNotGuardianForAccount.selector, bytes4(0xf3f77749)); } } diff --git a/test/unit/handlers/EmailRecoverySubjectHandler/validateRecoverySubject.t.sol b/test/unit/handlers/EmailRecoverySubjectHandler/validateRecoverySubject.t.sol index 8f1ec6be..89175380 100644 --- a/test/unit/handlers/EmailRecoverySubjectHandler/validateRecoverySubject.t.sol +++ b/test/unit/handlers/EmailRecoverySubjectHandler/validateRecoverySubject.t.sol @@ -32,7 +32,7 @@ contract EmailRecoverySubjectHandler_validateRecoverySubject_Test is UnitBase { ) ); emailRecoveryHandler.validateRecoverySubject( - invalidTemplateIdx, subjectParams, emailRecoveryManagerAddress + invalidTemplateIdx, subjectParams, recoveryModuleAddress ); } @@ -47,7 +47,7 @@ contract EmailRecoverySubjectHandler_validateRecoverySubject_Test is UnitBase { ) ); emailRecoveryHandler.validateRecoverySubject( - templateIdx, emptySubjectParams, emailRecoveryManagerAddress + templateIdx, emptySubjectParams, recoveryModuleAddress ); } @@ -66,7 +66,7 @@ contract EmailRecoverySubjectHandler_validateRecoverySubject_Test is UnitBase { ) ); emailRecoveryHandler.validateRecoverySubject( - templateIdx, longSubjectParams, emailRecoveryManagerAddress + templateIdx, longSubjectParams, recoveryModuleAddress ); } @@ -75,7 +75,7 @@ contract EmailRecoverySubjectHandler_validateRecoverySubject_Test is UnitBase { vm.expectRevert(EmailRecoverySubjectHandler.InvalidAccount.selector); emailRecoveryHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } @@ -88,7 +88,7 @@ contract EmailRecoverySubjectHandler_validateRecoverySubject_Test is UnitBase { ) ); emailRecoveryHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } @@ -103,7 +103,7 @@ contract EmailRecoverySubjectHandler_validateRecoverySubject_Test is UnitBase { ) ); emailRecoveryHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } @@ -112,7 +112,7 @@ contract EmailRecoverySubjectHandler_validateRecoverySubject_Test is UnitBase { vm.expectRevert("invalid hex prefix"); emailRecoveryHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } @@ -121,13 +121,13 @@ contract EmailRecoverySubjectHandler_validateRecoverySubject_Test is UnitBase { vm.expectRevert("invalid hex string length"); emailRecoveryHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } function test_ValidateRecoverySubject_Succeeds() public view { address accountFromEmail = emailRecoveryHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); assertEq(accountFromEmail, accountAddress); } diff --git a/test/unit/handlers/SafeRecoverySubjectHandler/validateRecoverySubject.t.sol b/test/unit/handlers/SafeRecoverySubjectHandler/validateRecoverySubject.t.sol index 56dd4f7a..a188615d 100644 --- a/test/unit/handlers/SafeRecoverySubjectHandler/validateRecoverySubject.t.sol +++ b/test/unit/handlers/SafeRecoverySubjectHandler/validateRecoverySubject.t.sol @@ -31,7 +31,7 @@ contract SafeRecoverySubjectHandler_validateRecoverySubject_Test is SafeUnitBase ) ); safeRecoverySubjectHandler.validateRecoverySubject( - invalidTemplateIdx, subjectParams, emailRecoveryManagerAddress + invalidTemplateIdx, subjectParams, recoveryModuleAddress ); } @@ -47,7 +47,7 @@ contract SafeRecoverySubjectHandler_validateRecoverySubject_Test is SafeUnitBase ) ); safeRecoverySubjectHandler.validateRecoverySubject( - templateIdx, emptySubjectParams, emailRecoveryManagerAddress + templateIdx, emptySubjectParams, recoveryModuleAddress ); } @@ -68,7 +68,7 @@ contract SafeRecoverySubjectHandler_validateRecoverySubject_Test is SafeUnitBase ) ); safeRecoverySubjectHandler.validateRecoverySubject( - templateIdx, longSubjectParams, emailRecoveryManagerAddress + templateIdx, longSubjectParams, recoveryModuleAddress ); } @@ -80,7 +80,7 @@ contract SafeRecoverySubjectHandler_validateRecoverySubject_Test is SafeUnitBase abi.encodeWithSelector(SafeRecoverySubjectHandler.InvalidOldOwner.selector, address(0)) ); safeRecoverySubjectHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } @@ -92,7 +92,7 @@ contract SafeRecoverySubjectHandler_validateRecoverySubject_Test is SafeUnitBase abi.encodeWithSelector(SafeRecoverySubjectHandler.InvalidNewOwner.selector, address(0)) ); safeRecoverySubjectHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } @@ -104,7 +104,7 @@ contract SafeRecoverySubjectHandler_validateRecoverySubject_Test is SafeUnitBase abi.encodeWithSelector(SafeRecoverySubjectHandler.InvalidNewOwner.selector, owner1) ); safeRecoverySubjectHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } @@ -118,7 +118,7 @@ contract SafeRecoverySubjectHandler_validateRecoverySubject_Test is SafeUnitBase ) ); safeRecoverySubjectHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } @@ -134,14 +134,14 @@ contract SafeRecoverySubjectHandler_validateRecoverySubject_Test is SafeUnitBase ) ); safeRecoverySubjectHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); } function test_ValidateRecoverySubject_Succeeds() public { skipIfNotSafeAccountType(); address accountFromEmail = safeRecoverySubjectHandler.validateRecoverySubject( - templateIdx, subjectParams, emailRecoveryManagerAddress + templateIdx, subjectParams, recoveryModuleAddress ); assertEq(accountFromEmail, accountAddress1); } diff --git a/test/unit/libraries/GuardianUtils/addGuardian.t.sol b/test/unit/libraries/GuardianUtils/addGuardian.t.sol index 31a6dbfd..9ab1eb79 100644 --- a/test/unit/libraries/GuardianUtils/addGuardian.t.sol +++ b/test/unit/libraries/GuardianUtils/addGuardian.t.sol @@ -5,9 +5,8 @@ import { console2 } from "forge-std/console2.sol"; import { ModuleKitHelpers } from "modulekit/ModuleKit.sol"; import { MODULE_TYPE_EXECUTOR } from "modulekit/external/ERC7579.sol"; import { UnitBase } from "../../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; contract GuardianUtils_addGuardian_Test is UnitBase { using ModuleKitHelpers for *; @@ -22,10 +21,10 @@ contract GuardianUtils_addGuardian_Test is UnitBase { vm.startPrank(accountAddress); vm.expectRevert( abi.encodeWithSelector( - GuardianUtils.InvalidGuardianAddress.selector, invalidGuardianAddress + IGuardianManager.InvalidGuardianAddress.selector, invalidGuardianAddress ) ); - emailRecoveryManager.addGuardian(invalidGuardianAddress, guardianWeights[0]); + emailRecoveryModule.addGuardian(invalidGuardianAddress, guardianWeights[0]); } function test_AddGuardian_RevertWhen_GuardianAddressIsAccountAddress() public { @@ -34,16 +33,16 @@ contract GuardianUtils_addGuardian_Test is UnitBase { vm.startPrank(accountAddress); vm.expectRevert( abi.encodeWithSelector( - GuardianUtils.InvalidGuardianAddress.selector, invalidGuardianAddress + IGuardianManager.InvalidGuardianAddress.selector, invalidGuardianAddress ) ); - emailRecoveryManager.addGuardian(invalidGuardianAddress, guardianWeights[0]); + emailRecoveryModule.addGuardian(invalidGuardianAddress, guardianWeights[0]); } function test_AddGuardian_RevertWhen_AddressAlreadyGuardian() public { vm.startPrank(accountAddress); - vm.expectRevert(GuardianUtils.AddressAlreadyGuardian.selector); - emailRecoveryManager.addGuardian(guardians[0], guardianWeights[0]); + vm.expectRevert(IGuardianManager.AddressAlreadyGuardian.selector); + emailRecoveryModule.addGuardian(guardians[0], guardianWeights[0]); } function test_AddGuardian_RevertWhen_InvalidGuardianWeight() public { @@ -51,8 +50,8 @@ contract GuardianUtils_addGuardian_Test is UnitBase { uint256 invalidGuardianWeight = 0; vm.startPrank(accountAddress); - vm.expectRevert(GuardianUtils.InvalidGuardianWeight.selector); - emailRecoveryManager.addGuardian(newGuardian, invalidGuardianWeight); + vm.expectRevert(IGuardianManager.InvalidGuardianWeight.selector); + emailRecoveryModule.addGuardian(newGuardian, invalidGuardianWeight); } function test_AddGuardian_AddGuardian_Succeeds() public { @@ -66,16 +65,16 @@ contract GuardianUtils_addGuardian_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); - emit GuardianUtils.AddedGuardian(accountAddress, newGuardian, newGuardianWeight); - emailRecoveryManager.addGuardian(newGuardian, newGuardianWeight); + emit IGuardianManager.AddedGuardian(accountAddress, newGuardian, newGuardianWeight); + emailRecoveryModule.addGuardian(newGuardian, newGuardianWeight); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, newGuardian); + emailRecoveryModule.getGuardian(accountAddress, newGuardian); assertEq(uint256(guardianStorage.status), uint256(GuardianStatus.REQUESTED)); assertEq(guardianStorage.weight, newGuardianWeight); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, expectedGuardianCount); assertEq(guardianConfig.totalWeight, expectedTotalWeight); assertEq(guardianConfig.acceptedWeight, expectedAcceptedWeight); diff --git a/test/unit/libraries/GuardianUtils/changeThreshold.t.sol b/test/unit/libraries/GuardianUtils/changeThreshold.t.sol index 89a6567b..2ccb8cde 100644 --- a/test/unit/libraries/GuardianUtils/changeThreshold.t.sol +++ b/test/unit/libraries/GuardianUtils/changeThreshold.t.sol @@ -3,8 +3,7 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; contract GuardianUtils_changeThreshold_Test is UnitBase { function setUp() public override { @@ -12,8 +11,8 @@ contract GuardianUtils_changeThreshold_Test is UnitBase { } function test_RevertWhen_SetupNotCalled() public { - vm.expectRevert(GuardianUtils.SetupNotCalled.selector); - emailRecoveryManager.changeThreshold(threshold); + vm.expectRevert(IGuardianManager.SetupNotCalled.selector); + emailRecoveryModule.changeThreshold(threshold); } function test_RevertWhen_ThresholdExceedsTotalWeight() public { @@ -22,18 +21,18 @@ contract GuardianUtils_changeThreshold_Test is UnitBase { vm.startPrank(accountAddress); vm.expectRevert( abi.encodeWithSelector( - GuardianUtils.ThresholdExceedsTotalWeight.selector, highThreshold, totalWeight + IGuardianManager.ThresholdExceedsTotalWeight.selector, highThreshold, totalWeight ) ); - emailRecoveryManager.changeThreshold(highThreshold); + emailRecoveryModule.changeThreshold(highThreshold); } function test_RevertWhen_ThresholdIsZero() public { uint256 zeroThreshold = 0; vm.startPrank(accountAddress); - vm.expectRevert(GuardianUtils.ThresholdCannotBeZero.selector); - emailRecoveryManager.changeThreshold(zeroThreshold); + vm.expectRevert(IGuardianManager.ThresholdCannotBeZero.selector); + emailRecoveryModule.changeThreshold(zeroThreshold); } function test_ChangeThreshold_IncreaseThreshold() public { @@ -41,11 +40,11 @@ contract GuardianUtils_changeThreshold_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); - emit GuardianUtils.ChangedThreshold(accountAddress, newThreshold); - emailRecoveryManager.changeThreshold(newThreshold); + emit IGuardianManager.ChangedThreshold(accountAddress, newThreshold); + emailRecoveryModule.changeThreshold(newThreshold); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, guardians.length); assertEq(guardianConfig.threshold, newThreshold); } @@ -55,11 +54,11 @@ contract GuardianUtils_changeThreshold_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); - emit GuardianUtils.ChangedThreshold(accountAddress, newThreshold); - emailRecoveryManager.changeThreshold(newThreshold); + emit IGuardianManager.ChangedThreshold(accountAddress, newThreshold); + emailRecoveryModule.changeThreshold(newThreshold); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, guardians.length); assertEq(guardianConfig.threshold, newThreshold); } diff --git a/test/unit/libraries/GuardianUtils/getGuardian.t.sol b/test/unit/libraries/GuardianUtils/getGuardian.t.sol index 05128310..abb537a5 100644 --- a/test/unit/libraries/GuardianUtils/getGuardian.t.sol +++ b/test/unit/libraries/GuardianUtils/getGuardian.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; import { UnitBase } from "../../UnitBase.t.sol"; diff --git a/test/unit/libraries/GuardianUtils/removeAllGuardians.t.sol b/test/unit/libraries/GuardianUtils/removeAllGuardians.t.sol index 54f80cc4..4ff1d5ac 100644 --- a/test/unit/libraries/GuardianUtils/removeAllGuardians.t.sol +++ b/test/unit/libraries/GuardianUtils/removeAllGuardians.t.sol @@ -3,17 +3,13 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; import { EnumerableGuardianMap, GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; contract GuardianUtils_removeAllGuardians_Test is UnitBase { - using GuardianUtils for mapping(address => EnumerableGuardianMap.AddressToGuardianMap); - function setUp() public override { super.setUp(); } @@ -23,20 +19,20 @@ contract GuardianUtils_removeAllGuardians_Test is UnitBase { acceptGuardian(accountSalt2); acceptGuardian(accountSalt3); - emailRecoveryManager.exposed_removeAllGuardians(accountAddress); + emailRecoveryModule.exposed_removeAllGuardians(accountAddress); GuardianStorage memory guardianStorage1 = - emailRecoveryManager.getGuardian(accountAddress, guardian1); + emailRecoveryModule.getGuardian(accountAddress, guardian1); assertEq(uint256(guardianStorage1.status), uint256(GuardianStatus.NONE)); assertEq(guardianStorage1.weight, 0); GuardianStorage memory guardianStorage2 = - emailRecoveryManager.getGuardian(accountAddress, guardian2); + emailRecoveryModule.getGuardian(accountAddress, guardian2); assertEq(uint256(guardianStorage2.status), uint256(GuardianStatus.NONE)); assertEq(guardianStorage2.weight, 0); GuardianStorage memory guardianStorage3 = - emailRecoveryManager.getGuardian(accountAddress, guardian3); + emailRecoveryModule.getGuardian(accountAddress, guardian3); assertEq(uint256(guardianStorage3.status), uint256(GuardianStatus.NONE)); assertEq(guardianStorage3.weight, 0); } diff --git a/test/unit/libraries/GuardianUtils/removeGuardian.t.sol b/test/unit/libraries/GuardianUtils/removeGuardian.t.sol index d666955e..6e39db8a 100644 --- a/test/unit/libraries/GuardianUtils/removeGuardian.t.sol +++ b/test/unit/libraries/GuardianUtils/removeGuardian.t.sol @@ -4,9 +4,8 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; contract GuardianUtils_removeGuardian_Test is UnitBase { function setUp() public override { @@ -17,8 +16,8 @@ contract GuardianUtils_removeGuardian_Test is UnitBase { address unauthorizedAccount = guardian1; vm.startPrank(unauthorizedAccount); - vm.expectRevert(GuardianUtils.AddressNotGuardianForAccount.selector); - emailRecoveryManager.removeGuardian(guardian1); + vm.expectRevert(IGuardianManager.AddressNotGuardianForAccount.selector); + emailRecoveryModule.removeGuardian(guardian1); } function test_RemoveGuardian_RevertWhen_ThresholdExceedsTotalWeight() public { @@ -36,12 +35,12 @@ contract GuardianUtils_removeGuardian_Test is UnitBase { vm.startPrank(accountAddress); vm.expectRevert( abi.encodeWithSelector( - GuardianUtils.ThresholdExceedsTotalWeight.selector, + IGuardianManager.ThresholdExceedsTotalWeight.selector, totalWeight - guardianWeights[1], threshold ) ); - emailRecoveryManager.removeGuardian(guardian); + emailRecoveryModule.removeGuardian(guardian); } function test_RemoveGuardian_Succeeds() public { @@ -55,15 +54,15 @@ contract GuardianUtils_removeGuardian_Test is UnitBase { // (weight < threshold == 3 < 3) = succeeds vm.startPrank(accountAddress); - emailRecoveryManager.removeGuardian(guardian); + emailRecoveryModule.removeGuardian(guardian); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, guardian); + emailRecoveryModule.getGuardian(accountAddress, guardian); assertEq(uint256(guardianStorage.status), uint256(GuardianStatus.NONE)); assertEq(guardianStorage.weight, 0); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, guardians.length - 1); assertEq(guardianConfig.totalWeight, totalWeight - guardianWeights[0]); assertEq(guardianConfig.acceptedWeight, 0); @@ -85,16 +84,16 @@ contract GuardianUtils_removeGuardian_Test is UnitBase { vm.startPrank(accountAddress); vm.expectEmit(); - emit GuardianUtils.RemovedGuardian(accountAddress, guardian, guardianWeights[0]); - emailRecoveryManager.removeGuardian(guardian); + emit IGuardianManager.RemovedGuardian(accountAddress, guardian, guardianWeights[0]); + emailRecoveryModule.removeGuardian(guardian); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, guardian); + emailRecoveryModule.getGuardian(accountAddress, guardian); assertEq(uint256(guardianStorage.status), uint256(GuardianStatus.NONE)); assertEq(guardianStorage.weight, 0); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, guardians.length - 1); assertEq(guardianConfig.totalWeight, totalWeight - guardianWeights[0]); diff --git a/test/unit/libraries/GuardianUtils/setupGuardians.t.sol b/test/unit/libraries/GuardianUtils/setupGuardians.t.sol index 6c71b0c3..c71e6d36 100644 --- a/test/unit/libraries/GuardianUtils/setupGuardians.t.sol +++ b/test/unit/libraries/GuardianUtils/setupGuardians.t.sol @@ -5,9 +5,8 @@ import { console2 } from "forge-std/console2.sol"; import { ModuleKitHelpers } from "modulekit/ModuleKit.sol"; import { MODULE_TYPE_EXECUTOR } from "modulekit/external/ERC7579.sol"; import { UnitBase } from "../../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; contract GuardianUtils_setupGuardians_Test is UnitBase { using ModuleKitHelpers for *; @@ -25,12 +24,12 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { vm.expectRevert( abi.encodeWithSelector( - GuardianUtils.IncorrectNumberOfWeights.selector, + IGuardianManager.IncorrectNumberOfWeights.selector, guardians.length, invalidGuardianWeights.length ) ); - emailRecoveryManager.exposed_setupGuardians( + emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, invalidGuardianWeights, threshold ); } @@ -38,8 +37,8 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { function test_SetupGuardians_RevertWhen_ThresholdIsZero() public { uint256 zeroThreshold = 0; - vm.expectRevert(GuardianUtils.ThresholdCannotBeZero.selector); - emailRecoveryManager.exposed_setupGuardians( + vm.expectRevert(IGuardianManager.ThresholdCannotBeZero.selector); + emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, guardianWeights, zeroThreshold ); } @@ -48,9 +47,9 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { guardians[0] = address(0); vm.expectRevert( - abi.encodeWithSelector(GuardianUtils.InvalidGuardianAddress.selector, guardians[0]) + abi.encodeWithSelector(IGuardianManager.InvalidGuardianAddress.selector, guardians[0]) ); - emailRecoveryManager.exposed_setupGuardians( + emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, guardianWeights, threshold ); } @@ -59,9 +58,9 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { guardians[0] = accountAddress; vm.expectRevert( - abi.encodeWithSelector(GuardianUtils.InvalidGuardianAddress.selector, guardians[0]) + abi.encodeWithSelector(IGuardianManager.InvalidGuardianAddress.selector, guardians[0]) ); - emailRecoveryManager.exposed_setupGuardians( + emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, guardianWeights, threshold ); } @@ -73,8 +72,8 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { guardianWeights[0] = 0; - vm.expectRevert(GuardianUtils.InvalidGuardianWeight.selector); - emailRecoveryManager.exposed_setupGuardians( + vm.expectRevert(IGuardianManager.InvalidGuardianWeight.selector); + emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, guardianWeights, threshold ); } @@ -82,8 +81,8 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { function test_SetupGuardians_RevertWhen_AddressAlreadyGuardian() public { guardians[0] = guardians[1]; - vm.expectRevert(GuardianUtils.AddressAlreadyGuardian.selector); - emailRecoveryManager.exposed_setupGuardians( + vm.expectRevert(IGuardianManager.AddressAlreadyGuardian.selector); + emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, guardianWeights, threshold ); } @@ -97,10 +96,10 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { vm.expectRevert( abi.encodeWithSelector( - GuardianUtils.ThresholdExceedsTotalWeight.selector, invalidThreshold, totalWeight + IGuardianManager.ThresholdExceedsTotalWeight.selector, invalidThreshold, totalWeight ) ); - emailRecoveryManager.exposed_setupGuardians( + emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, guardianWeights, invalidThreshold ); } @@ -115,16 +114,16 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { instance.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, ""); vm.stopPrank(); - (uint256 guardianCount, uint256 totalWeight) = emailRecoveryManager.exposed_setupGuardians( + (uint256 guardianCount, uint256 totalWeight) = emailRecoveryModule.exposed_setupGuardians( accountAddress, guardians, guardianWeights, threshold ); GuardianStorage memory guardianStorage1 = - emailRecoveryManager.getGuardian(accountAddress, guardians[0]); + emailRecoveryModule.getGuardian(accountAddress, guardians[0]); GuardianStorage memory guardianStorage2 = - emailRecoveryManager.getGuardian(accountAddress, guardians[1]); + emailRecoveryModule.getGuardian(accountAddress, guardians[1]); GuardianStorage memory guardianStorage3 = - emailRecoveryManager.getGuardian(accountAddress, guardians[2]); + emailRecoveryModule.getGuardian(accountAddress, guardians[2]); assertEq(uint256(guardianStorage1.status), uint256(GuardianStatus.REQUESTED)); assertEq(guardianStorage1.weight, guardianWeights[0]); assertEq(uint256(guardianStorage2.status), uint256(GuardianStatus.REQUESTED)); @@ -135,8 +134,8 @@ contract GuardianUtils_setupGuardians_Test is UnitBase { assertEq(guardianCount, expectedGuardianCount); assertEq(totalWeight, expectedTotalWeight); - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - emailRecoveryManager.getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); assertEq(guardianConfig.guardianCount, expectedGuardianCount); assertEq(guardianConfig.totalWeight, expectedTotalWeight); assertEq(guardianConfig.acceptedWeight, expectedAcceptedWeight); diff --git a/test/unit/libraries/GuardianUtils/updateGuardianStatus.t.sol b/test/unit/libraries/GuardianUtils/updateGuardianStatus.t.sol index 07399cd6..4bfe79db 100644 --- a/test/unit/libraries/GuardianUtils/updateGuardianStatus.t.sol +++ b/test/unit/libraries/GuardianUtils/updateGuardianStatus.t.sol @@ -4,10 +4,9 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { ModuleKitHelpers } from "modulekit/ModuleKit.sol"; import { MODULE_TYPE_EXECUTOR } from "modulekit/external/ERC7579.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; import { GuardianStorage, GuardianStatus } from "src/libraries/EnumerableGuardianMap.sol"; import { UnitBase } from "../../UnitBase.t.sol"; -import { GuardianUtils } from "src/libraries/GuardianUtils.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; contract GuardianUtils_updateGuardianStatus_Test is UnitBase { using ModuleKitHelpers for *; @@ -24,44 +23,50 @@ contract GuardianUtils_updateGuardianStatus_Test is UnitBase { GuardianStatus newStatus = GuardianStatus.NONE; vm.expectRevert( - abi.encodeWithSelector(GuardianUtils.StatusCannotBeTheSame.selector, uint256(newStatus)) + abi.encodeWithSelector( + IGuardianManager.StatusCannotBeTheSame.selector, uint256(newStatus) + ) ); - emailRecoveryManager.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); + emailRecoveryModule.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); } function test_UpdateGuardianStatus_RevertWhen_StatusIsAlreadyREQUESTED() public { GuardianStatus newStatus = GuardianStatus.REQUESTED; - emailRecoveryManager.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); + emailRecoveryModule.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); vm.expectRevert( - abi.encodeWithSelector(GuardianUtils.StatusCannotBeTheSame.selector, uint256(newStatus)) + abi.encodeWithSelector( + IGuardianManager.StatusCannotBeTheSame.selector, uint256(newStatus) + ) ); - emailRecoveryManager.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); + emailRecoveryModule.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); } function test_UpdateGuardianStatus_RevertWhen_StatusIsAlreadyACCEPTED() public { GuardianStatus newStatus = GuardianStatus.ACCEPTED; - emailRecoveryManager.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); + emailRecoveryModule.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); vm.expectRevert( - abi.encodeWithSelector(GuardianUtils.StatusCannotBeTheSame.selector, uint256(newStatus)) + abi.encodeWithSelector( + IGuardianManager.StatusCannotBeTheSame.selector, uint256(newStatus) + ) ); - emailRecoveryManager.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); + emailRecoveryModule.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); } function test_UpdateGuardianStatus_UpdatesStatusToNONE() public { GuardianStatus newStatus = GuardianStatus.NONE; - emailRecoveryManager.exposed_updateGuardianStatus( + emailRecoveryModule.exposed_updateGuardianStatus( accountAddress, guardian1, GuardianStatus.REQUESTED ); - emailRecoveryManager.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); + emailRecoveryModule.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, guardian1); + emailRecoveryModule.getGuardian(accountAddress, guardian1); assertEq(uint256(guardianStorage.status), uint256(newStatus)); assertEq(guardianStorage.weight, 0); } @@ -69,10 +74,10 @@ contract GuardianUtils_updateGuardianStatus_Test is UnitBase { function test_UpdateGuardianStatus_UpdatesStatusToREQUESTED() public { GuardianStatus newStatus = GuardianStatus.REQUESTED; - emailRecoveryManager.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); + emailRecoveryModule.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, guardian1); + emailRecoveryModule.getGuardian(accountAddress, guardian1); assertEq(uint256(guardianStorage.status), uint256(newStatus)); assertEq(guardianStorage.weight, 0); } @@ -81,11 +86,11 @@ contract GuardianUtils_updateGuardianStatus_Test is UnitBase { GuardianStatus newStatus = GuardianStatus.ACCEPTED; vm.expectEmit(); - emit GuardianUtils.GuardianStatusUpdated(accountAddress, guardian1, newStatus); - emailRecoveryManager.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); + emit IGuardianManager.GuardianStatusUpdated(accountAddress, guardian1, newStatus); + emailRecoveryModule.exposed_updateGuardianStatus(accountAddress, guardian1, newStatus); GuardianStorage memory guardianStorage = - emailRecoveryManager.getGuardian(accountAddress, guardian1); + emailRecoveryModule.getGuardian(accountAddress, guardian1); assertEq(uint256(guardianStorage.status), uint256(newStatus)); assertEq(guardianStorage.weight, 0); } diff --git a/test/unit/modules/EmailRecoveryModule/EmailRecoveryModuleBase.t.sol b/test/unit/modules/EmailRecoveryModule/EmailRecoveryModuleBase.t.sol index 7212e2ca..3f008344 100644 --- a/test/unit/modules/EmailRecoveryModule/EmailRecoveryModuleBase.t.sol +++ b/test/unit/modules/EmailRecoveryModule/EmailRecoveryModuleBase.t.sol @@ -21,10 +21,8 @@ import { import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { ECDSA } from "solady/utils/ECDSA.sol"; -import { EmailRecoveryManagerHarness } from "../../EmailRecoveryManagerHarness.sol"; import { EmailRecoverySubjectHandler } from "src/handlers/EmailRecoverySubjectHandler.sol"; -import { EmailRecoveryModule } from "src/modules/EmailRecoveryModule.sol"; -import { EmailRecoveryManager } from "src/EmailRecoveryManager.sol"; +import { EmailRecoveryModuleHarness } from "../../EmailRecoveryModuleHarness.sol"; import { EmailRecoveryFactory } from "src/factories/EmailRecoveryFactory.sol"; import { OwnableValidator } from "src/test/OwnableValidator.sol"; import { MockGroth16Verifier } from "src/test/MockGroth16Verifier.sol"; @@ -42,11 +40,8 @@ abstract contract EmailRecoveryModuleBase is RhinestoneModuleKit, Test { EmailRecoveryFactory emailRecoveryFactory; EmailRecoverySubjectHandler emailRecoveryHandler; - EmailRecoveryManagerHarness emailRecoveryManager; - EmailRecoveryModule emailRecoveryModule; + EmailRecoveryModuleHarness emailRecoveryModule; - // EmailRecoveryManager emailRecoveryManager; - address emailRecoveryManagerAddress; address recoveryModuleAddress; address validatorAddress; @@ -115,22 +110,19 @@ abstract contract EmailRecoveryModuleBase is RhinestoneModuleKit, Test { recoveryCalldata = abi.encodeWithSelector(functionSelector, newOwner); calldataHash = keccak256(recoveryCalldata); - // Deploy handler, manager and module + // Deploy handler and module emailRecoveryHandler = new EmailRecoverySubjectHandler(); emailRecoveryFactory = new EmailRecoveryFactory(address(verifier), address(emailAuthImpl)); - emailRecoveryManager = new EmailRecoveryManagerHarness( + emailRecoveryModule = new EmailRecoveryModuleHarness( address(verifier), address(dkimRegistry), address(emailAuthImpl), - address(emailRecoveryHandler) + address(emailRecoveryHandler), + validatorAddress, + functionSelector ); - emailRecoveryManagerAddress = address(emailRecoveryManager); - - emailRecoveryModule = - new EmailRecoveryModule(emailRecoveryManagerAddress, validatorAddress, functionSelector); recoveryModuleAddress = address(emailRecoveryModule); - emailRecoveryManager.initialize(recoveryModuleAddress); // Deploy and fund the account instance = makeAccountInstance("account"); @@ -142,9 +134,9 @@ abstract contract EmailRecoveryModuleBase is RhinestoneModuleKit, Test { accountSalt3 = keccak256(abi.encode("account salt 3")); // Compute guardian addresses - guardian1 = emailRecoveryManager.computeEmailAuthAddress(instance.account, accountSalt1); - guardian2 = emailRecoveryManager.computeEmailAuthAddress(instance.account, accountSalt2); - guardian3 = emailRecoveryManager.computeEmailAuthAddress(instance.account, accountSalt3); + guardian1 = emailRecoveryModule.computeEmailAuthAddress(instance.account, accountSalt1); + guardian2 = emailRecoveryModule.computeEmailAuthAddress(instance.account, accountSalt2); + guardian3 = emailRecoveryModule.computeEmailAuthAddress(instance.account, accountSalt3); guardians = new address[](3); guardians[0] = guardian1; @@ -242,13 +234,13 @@ abstract contract EmailRecoveryModuleBase is RhinestoneModuleKit, Test { bytes[] memory subjectParamsForAcceptance = new bytes[](1); subjectParamsForAcceptance[0] = abi.encode(accountAddress); EmailAuthMsg memory emailAuthMsg = EmailAuthMsg({ - templateId: emailRecoveryManager.computeAcceptanceTemplateId(templateIdx), + templateId: emailRecoveryModule.computeAcceptanceTemplateId(templateIdx), subjectParams: subjectParamsForAcceptance, skipedSubjectPrefix: 0, proof: emailProof }); - emailRecoveryManager.handleAcceptance(emailAuthMsg, templateIdx); + emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx); } function handleRecovery( @@ -276,11 +268,11 @@ abstract contract EmailRecoveryModuleBase is RhinestoneModuleKit, Test { subjectParamsForRecovery[2] = abi.encode(calldataHashString); EmailAuthMsg memory emailAuthMsg = EmailAuthMsg({ - templateId: emailRecoveryManager.computeRecoveryTemplateId(templateIdx), + templateId: emailRecoveryModule.computeRecoveryTemplateId(templateIdx), subjectParams: subjectParamsForRecovery, skipedSubjectPrefix: 0, proof: emailProof }); - emailRecoveryManager.handleRecovery(emailAuthMsg, templateIdx); + emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx); } } diff --git a/test/unit/modules/EmailRecoveryModule/canStartRecoveryRequest.t.sol b/test/unit/modules/EmailRecoveryModule/canStartRecoveryRequest.t.sol index 02070aae..953a892e 100644 --- a/test/unit/modules/EmailRecoveryModule/canStartRecoveryRequest.t.sol +++ b/test/unit/modules/EmailRecoveryModule/canStartRecoveryRequest.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; import { EmailRecoveryModuleBase } from "./EmailRecoveryModuleBase.t.sol"; contract EmailRecoveryModule_canStartRecoveryRequest_Test is EmailRecoveryModuleBase { @@ -15,8 +15,8 @@ contract EmailRecoveryModule_canStartRecoveryRequest_Test is EmailRecoveryModule bool canStartRecoveryRequest = emailRecoveryModule.canStartRecoveryRequest(accountAddress); // Checking accepted weight is what we expect for this test case - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); // No guardians have accepted assertFalse(canStartRecoveryRequest); @@ -31,8 +31,8 @@ contract EmailRecoveryModule_canStartRecoveryRequest_Test is EmailRecoveryModule bool canStartRecoveryRequest = emailRecoveryModule.canStartRecoveryRequest(accountAddress); // Checking accepted weight is what we expect for this test case - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); // Enough guardians have accepted so that accepted weight is higher than the threshold assertTrue(canStartRecoveryRequest); @@ -46,8 +46,8 @@ contract EmailRecoveryModule_canStartRecoveryRequest_Test is EmailRecoveryModule bool canStartRecoveryRequest = emailRecoveryModule.canStartRecoveryRequest(accountAddress); // Checking accepted weight is what we expect for this test case - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); // Enough guardians have accepted so that accepted weight is equal to the threshold assertTrue(canStartRecoveryRequest); diff --git a/test/unit/modules/EmailRecoveryModule/constructor.t.sol b/test/unit/modules/EmailRecoveryModule/constructor.t.sol index b182f9bf..3921c8a0 100644 --- a/test/unit/modules/EmailRecoveryModule/constructor.t.sol +++ b/test/unit/modules/EmailRecoveryModule/constructor.t.sol @@ -13,18 +13,19 @@ contract EmailRecoveryManager_constructor_Test is EmailRecoveryModuleBase { super.setUp(); } - function test_Constructor_RevertWhen_InvalidManager() public { - address invalidManager = address(0); - vm.expectRevert(EmailRecoveryModule.InvalidManager.selector); - new EmailRecoveryModule(invalidManager, validatorAddress, functionSelector); - } - function test_Constructor_RevertWhen_InvalidValidator() public { address invalidValidator = address(0); vm.expectRevert( abi.encodeWithSelector(EmailRecoveryModule.InvalidValidator.selector, invalidValidator) ); - new EmailRecoveryModule(emailRecoveryManagerAddress, invalidValidator, functionSelector); + new EmailRecoveryModule( + address(verifier), + address(dkimRegistry), + address(emailAuthImpl), + address(emailRecoveryHandler), + invalidValidator, + functionSelector + ); } function test_Constructor_RevertWhen_UnsafeOnInstallSelector() public { @@ -34,7 +35,12 @@ contract EmailRecoveryManager_constructor_Test is EmailRecoveryModuleBase { ) ); new EmailRecoveryModule( - emailRecoveryManagerAddress, validatorAddress, IModule.onInstall.selector + address(verifier), + address(dkimRegistry), + address(emailAuthImpl), + address(emailRecoveryHandler), + validatorAddress, + IModule.onInstall.selector ); } @@ -45,7 +51,12 @@ contract EmailRecoveryManager_constructor_Test is EmailRecoveryModuleBase { ) ); new EmailRecoveryModule( - emailRecoveryManagerAddress, validatorAddress, IModule.onUninstall.selector + address(verifier), + address(dkimRegistry), + address(emailAuthImpl), + address(emailRecoveryHandler), + validatorAddress, + IModule.onUninstall.selector ); } @@ -86,14 +97,26 @@ contract EmailRecoveryManager_constructor_Test is EmailRecoveryModuleBase { vm.expectRevert( abi.encodeWithSelector(EmailRecoveryModule.InvalidSelector.selector, bytes4(0)) ); - new EmailRecoveryModule(emailRecoveryManagerAddress, validatorAddress, bytes4(0)); + new EmailRecoveryModule( + address(verifier), + address(dkimRegistry), + address(emailAuthImpl), + address(emailRecoveryHandler), + validatorAddress, + bytes4(0) + ); } function test_Constructor() public { - EmailRecoveryModule emailRecoveryModule = - new EmailRecoveryModule(emailRecoveryManagerAddress, validatorAddress, functionSelector); + EmailRecoveryModule emailRecoveryModule = new EmailRecoveryModule( + address(verifier), + address(dkimRegistry), + address(emailAuthImpl), + address(emailRecoveryHandler), + validatorAddress, + functionSelector + ); - assertEq(emailRecoveryManagerAddress, emailRecoveryModule.emailRecoveryManager()); assertEq(validatorAddress, emailRecoveryModule.validator()); assertEq(functionSelector, emailRecoveryModule.selector()); } diff --git a/test/unit/modules/EmailRecoveryModule/getTrustedRecoveryManager.t.sol b/test/unit/modules/EmailRecoveryModule/getTrustedRecoveryManager.t.sol deleted file mode 100644 index eaff1f43..00000000 --- a/test/unit/modules/EmailRecoveryModule/getTrustedRecoveryManager.t.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import { console2 } from "forge-std/console2.sol"; -import { EmailRecoveryModuleBase } from "./EmailRecoveryModuleBase.t.sol"; - -contract EmailRecoveryModule_getTrustedRecoveryManager_Test is EmailRecoveryModuleBase { - function setUp() public override { - super.setUp(); - } - - function test_GetTrustedRecoveryManager_Succeeds() public view { } -} diff --git a/test/unit/modules/EmailRecoveryModule/recover.t.sol b/test/unit/modules/EmailRecoveryModule/recover.t.sol index 6e32decd..29324fff 100644 --- a/test/unit/modules/EmailRecoveryModule/recover.t.sol +++ b/test/unit/modules/EmailRecoveryModule/recover.t.sol @@ -10,17 +10,12 @@ contract EmailRecoveryModule_recover_Test is EmailRecoveryModuleBase { super.setUp(); } - function test_Recover_RevertWhen_NotTrustedRecoveryContract() public { - vm.expectRevert(EmailRecoveryModule.NotTrustedRecoveryManager.selector); - emailRecoveryModule.recover(accountAddress, recoveryCalldata); - } - function test_Recover_RevertWhen_RecoveryNotAuthorizedForAccount() public { address invalidAccount = address(1); - vm.startPrank(emailRecoveryManagerAddress); + vm.startPrank(recoveryModuleAddress); vm.expectRevert(EmailRecoveryModule.RecoveryNotAuthorizedForAccount.selector); - emailRecoveryModule.recover(invalidAccount, recoveryCalldata); + emailRecoveryModule.exposed_recover(invalidAccount, recoveryCalldata); } function test_Recover_RevertWhen_InvalidCalldataSelector() public { @@ -28,18 +23,18 @@ contract EmailRecoveryModule_recover_Test is EmailRecoveryModuleBase { bytes memory invalidCalldata = abi.encodeWithSelector(invalidSelector, accountAddress, recoveryModuleAddress, newOwner); - vm.startPrank(emailRecoveryManagerAddress); + vm.startPrank(recoveryModuleAddress); vm.expectRevert( abi.encodeWithSelector(EmailRecoveryModule.InvalidSelector.selector, invalidSelector) ); - emailRecoveryModule.recover(accountAddress, invalidCalldata); + emailRecoveryModule.exposed_recover(accountAddress, invalidCalldata); } function test_Recover_Succeeds() public { - vm.startPrank(emailRecoveryManagerAddress); + vm.startPrank(recoveryModuleAddress); vm.expectEmit(); emit EmailRecoveryModule.RecoveryExecuted(accountAddress, validatorAddress); - emailRecoveryModule.recover(accountAddress, recoveryCalldata); + emailRecoveryModule.exposed_recover(accountAddress, recoveryCalldata); address updatedOwner = validator.owners(accountAddress); assertEq(updatedOwner, newOwner); diff --git a/test/unit/modules/UniversalEmailRecoveryModule/canStartRecoveryRequest.t.sol b/test/unit/modules/UniversalEmailRecoveryModule/canStartRecoveryRequest.t.sol index ef003227..3450e30d 100644 --- a/test/unit/modules/UniversalEmailRecoveryModule/canStartRecoveryRequest.t.sol +++ b/test/unit/modules/UniversalEmailRecoveryModule/canStartRecoveryRequest.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.25; import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../../UnitBase.t.sol"; -import { IEmailRecoveryManager } from "src/interfaces/IEmailRecoveryManager.sol"; +import { IGuardianManager } from "src/interfaces/IGuardianManager.sol"; contract UniversalEmailRecoveryModule_canStartRecoveryRequest_Test is UnitBase { function setUp() public override { @@ -15,8 +15,8 @@ contract UniversalEmailRecoveryModule_canStartRecoveryRequest_Test is UnitBase { emailRecoveryModule.canStartRecoveryRequest(accountAddress, validatorAddress); // Checking accepted weight and sentinel list storage are what we expect for this test case - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); bool contains = emailRecoveryModule.workaround_validatorsContains(accountAddress, validatorAddress); @@ -35,8 +35,8 @@ contract UniversalEmailRecoveryModule_canStartRecoveryRequest_Test is UnitBase { emailRecoveryModule.canStartRecoveryRequest(accountAddress, invalidValidatorAddress); // Checking accepted weight and sentinel list storage are what we expect for this test case - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); bool contains = emailRecoveryModule.workaround_validatorsContains( accountAddress, invalidValidatorAddress ); @@ -59,8 +59,8 @@ contract UniversalEmailRecoveryModule_canStartRecoveryRequest_Test is UnitBase { emailRecoveryModule.canStartRecoveryRequest(accountAddress, validatorAddress); // Checking accepted weight and sentinel list storage are what we expect for this test case - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); bool contains = emailRecoveryModule.workaround_validatorsContains(accountAddress, validatorAddress); @@ -81,8 +81,8 @@ contract UniversalEmailRecoveryModule_canStartRecoveryRequest_Test is UnitBase { emailRecoveryModule.canStartRecoveryRequest(accountAddress, validatorAddress); // Checking accepted weight and sentinel list storage are what we expect for this test case - IEmailRecoveryManager.GuardianConfig memory guardianConfig = - IEmailRecoveryManager(emailRecoveryManager).getGuardianConfig(accountAddress); + IGuardianManager.GuardianConfig memory guardianConfig = + emailRecoveryModule.getGuardianConfig(accountAddress); bool contains = emailRecoveryModule.workaround_validatorsContains(accountAddress, validatorAddress); diff --git a/test/unit/modules/UniversalEmailRecoveryModule/constructor.t.sol b/test/unit/modules/UniversalEmailRecoveryModule/constructor.t.sol index b6e581c2..0f57dcb5 100644 --- a/test/unit/modules/UniversalEmailRecoveryModule/constructor.t.sol +++ b/test/unit/modules/UniversalEmailRecoveryModule/constructor.t.sol @@ -5,21 +5,17 @@ import { console2 } from "forge-std/console2.sol"; import { UnitBase } from "../../UnitBase.t.sol"; import { UniversalEmailRecoveryModule } from "src/modules/UniversalEmailRecoveryModule.sol"; -contract UniversalEmailRecoveryManager_constructor_Test is UnitBase { +contract UniversalEmailRecoveryModule_constructor_Test is UnitBase { function setUp() public override { super.setUp(); } - function test_Constructor_RevertWhen_InvalidManager() public { - address invalidManager = address(0); - vm.expectRevert(UniversalEmailRecoveryModule.InvalidManager.selector); - new UniversalEmailRecoveryModule(invalidManager); - } - function test_Constructor() public { - UniversalEmailRecoveryModule emailRecoveryModule = - new UniversalEmailRecoveryModule(emailRecoveryManagerAddress); - - assertEq(emailRecoveryManagerAddress, emailRecoveryModule.emailRecoveryManager()); + UniversalEmailRecoveryModule emailRecoveryModule = new UniversalEmailRecoveryModule( + address(verifier), + address(dkimRegistry), + address(emailAuthImpl), + address(emailRecoveryHandler) + ); } } diff --git a/test/unit/modules/UniversalEmailRecoveryModule/getTrustedRecoveryManager.t.sol b/test/unit/modules/UniversalEmailRecoveryModule/getTrustedRecoveryManager.t.sol deleted file mode 100644 index abf080ae..00000000 --- a/test/unit/modules/UniversalEmailRecoveryModule/getTrustedRecoveryManager.t.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import { console2 } from "forge-std/console2.sol"; -import { UnitBase } from "../../UnitBase.t.sol"; - -contract UniversalEmailRecoveryModule_getTrustedRecoveryManager_Test is UnitBase { - function setUp() public override { - super.setUp(); - } - - function test_GetTrustedRecoveryManager_Succeeds() public view { } -} diff --git a/test/unit/modules/UniversalEmailRecoveryModule/onInstall.t.sol b/test/unit/modules/UniversalEmailRecoveryModule/onInstall.t.sol index 1f93542a..2c4c324e 100644 --- a/test/unit/modules/UniversalEmailRecoveryModule/onInstall.t.sol +++ b/test/unit/modules/UniversalEmailRecoveryModule/onInstall.t.sol @@ -21,7 +21,7 @@ contract UniversalEmailRecoveryModule_onInstall_Test is UnitBase { bytes memory emptyData = new bytes(0); assertEq(emptyData.length, 0); - // FIXME: Error not thrown despite the data being passed has a length of zero + // FIXME: call function directly to detect error // vm.expectRevert(UniversalEmailRecoveryModule.InvalidOnInstallData.selector); // When installing with empty data and not expecting a revert, the test fails diff --git a/test/unit/modules/UniversalEmailRecoveryModule/recover.t.sol b/test/unit/modules/UniversalEmailRecoveryModule/recover.t.sol index 78f88735..3857dce6 100644 --- a/test/unit/modules/UniversalEmailRecoveryModule/recover.t.sol +++ b/test/unit/modules/UniversalEmailRecoveryModule/recover.t.sol @@ -10,21 +10,16 @@ contract UniversalEmailRecoveryModule_recover_Test is UnitBase { super.setUp(); } - function test_Recover_RevertWhen_NotTrustedRecoveryContract() public { - vm.expectRevert(UniversalEmailRecoveryModule.NotTrustedRecoveryManager.selector); - emailRecoveryModule.recover(accountAddress, recoveryCalldata); - } - function test_Recover_RevertWhen_InvalidAccount() public { address invalidAccount = address(1); - vm.startPrank(emailRecoveryManagerAddress); + vm.startPrank(recoveryModuleAddress); vm.expectRevert( abi.encodeWithSelector( UniversalEmailRecoveryModule.InvalidSelector.selector, functionSelector ) ); - emailRecoveryModule.recover(invalidAccount, recoveryCalldata); + emailRecoveryModule.exposed_recover(invalidAccount, recoveryCalldata); } function test_Recover_RevertWhen_InvalidCalldataSelector() public { @@ -33,13 +28,13 @@ contract UniversalEmailRecoveryModule_recover_Test is UnitBase { abi.encodeWithSelector(invalidSelector, accountAddress, recoveryModuleAddress, newOwner); bytes memory invalidCalldata = abi.encode(accountAddress, changeOwnerCalldata); - vm.startPrank(emailRecoveryManagerAddress); + vm.startPrank(recoveryModuleAddress); vm.expectRevert( abi.encodeWithSelector( UniversalEmailRecoveryModule.InvalidSelector.selector, invalidSelector ) ); - emailRecoveryModule.recover(accountAddress, invalidCalldata); + emailRecoveryModule.exposed_recover(accountAddress, invalidCalldata); } function test_Recover_RevertWhen_InvalidZeroCalldataSelector() public { @@ -51,20 +46,20 @@ contract UniversalEmailRecoveryModule_recover_Test is UnitBase { expectedSelector := mload(add(invalidChangeOwnerCaldata, 32)) } - vm.startPrank(emailRecoveryManagerAddress); + vm.startPrank(recoveryModuleAddress); vm.expectRevert( abi.encodeWithSelector( UniversalEmailRecoveryModule.InvalidSelector.selector, expectedSelector ) ); - emailRecoveryModule.recover(accountAddress, invalidCalldata); + emailRecoveryModule.exposed_recover(accountAddress, invalidCalldata); } function test_Recover_Succeeds() public { - vm.startPrank(emailRecoveryManagerAddress); + vm.startPrank(recoveryModuleAddress); vm.expectEmit(); emit UniversalEmailRecoveryModule.RecoveryExecuted(accountAddress, validatorAddress); - emailRecoveryModule.recover(accountAddress, recoveryCalldata); + emailRecoveryModule.exposed_recover(accountAddress, recoveryCalldata); address updatedOwner = validator.owners(accountAddress); assertEq(updatedOwner, newOwner);