Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Commit

Permalink
Add router manager and simplify recovery config
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnGuilding committed Apr 19, 2024
1 parent ba17907 commit e450c20
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 65 deletions.
38 changes: 38 additions & 0 deletions packages/plugins/src/safe/RouterManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License.Idenitifer: MIT
pragma solidity ^0.8.0;

interface IRouterManager {
struct SafeAccountInfo {
address safe;
address previousOwnerInLinkedList;
}

function getSafeAccountInfo(
address recoveryRouter
) external view returns (SafeAccountInfo memory);

function getRouterForSafe(address safe) external view returns (address);
}

abstract contract RouterManager is IRouterManager {
/** Mapping of email account recovery router contracts to safe details needed to complete recovery */
mapping(address => SafeAccountInfo) public recoveryRouterToSafeInfo;

/** Mapping of safe account addresses to email account recovery router contracts**/
/** These are stored for frontends to easily find the router contract address from the given safe account address**/
mapping(address => address) public safeToRecoveryRouter;

/// @inheritdoc IRouterManager
function getSafeAccountInfo(
address recoveryRouter
) external view override returns (SafeAccountInfo memory) {
return recoveryRouterToSafeInfo[recoveryRouter];
}

/// @inheritdoc IRouterManager
function getRouterForSafe(
address safe
) external view override returns (address) {
return safeToRecoveryRouter[safe];
}
}
36 changes: 9 additions & 27 deletions packages/plugins/src/safe/SafeZkEmailRecoveryPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.0;

import {EmailAccountRecovery} from "ether-email-auth/packages/contracts/src/EmailAccountRecovery.sol";
import {GuardianManager} from "./GuardianManager.sol";
import {RouterManager} from "./RouterManager.sol";
import {ISafeZkEmailRecoveryPlugin} from "./interface/ISafeZkEmailRecoveryPlugin.sol";
import {ISafe} from "./utils/Safe4337Base.sol";
import {EmailAccountRecoveryRouter} from "./EmailAccountRecoveryRouter.sol";
Expand All @@ -25,22 +26,16 @@ import "forge-std/console2.sol";
*/
contract SafeZkEmailRecoveryPlugin is
GuardianManager,
RouterManager,
ISafeZkEmailRecoveryPlugin,
EmailAccountRecovery
{
/** Mapping of safe address to recovery config */
mapping(address => RecoveryConfig) public recoveryConfigs;
/** Mapping of safe address to recovery delay */
mapping(address => uint256) public recoveryDelays;

/** Mapping of safe address to recovery request */
mapping(address => RecoveryRequest) public recoveryRequests;

/** Mapping of email account recovery router contracts to safe details needed to complete recovery */
mapping(address => SafeAccountInfo) public recoveryRouterToSafeInfo;

/** Mapping of safe account addresses to email account recovery router contracts**/
/** These are stored for frontends to easily find the router contract address from the given safe account address**/
mapping(address => address) public safeToRecoveryRouter;

constructor(
address _verifier,
address _dkimRegistry,
Expand All @@ -52,10 +47,8 @@ contract SafeZkEmailRecoveryPlugin is
}

/// @inheritdoc ISafeZkEmailRecoveryPlugin
function getRecoveryConfig(
address safe
) external view returns (RecoveryConfig memory) {
return recoveryConfigs[safe];
function getRecoveryDelay(address safe) external view returns (uint256) {
return recoveryDelays[safe];
}

/// @inheritdoc ISafeZkEmailRecoveryPlugin
Expand All @@ -65,12 +58,6 @@ contract SafeZkEmailRecoveryPlugin is
return recoveryRequests[safe];
}

// TODO: test
/// @inheritdoc ISafeZkEmailRecoveryPlugin
function getRouterForSafe(address safe) external view returns (address) {
return safeToRecoveryRouter[safe];
}

/// @inheritdoc EmailAccountRecovery
function acceptanceSubjectTemplates()
public
Expand Down Expand Up @@ -146,7 +133,7 @@ contract SafeZkEmailRecoveryPlugin is
);
safeToRecoveryRouter[safe] = routerAddress;

recoveryConfigs[safe] = RecoveryConfig({recoveryDelay: recoveryDelay});
recoveryDelays[safe] = recoveryDelay;

emit RecoveryConfigured(
safe,
Expand Down Expand Up @@ -209,7 +196,6 @@ contract SafeZkEmailRecoveryPlugin is
if (isExistingOwner) revert InvalidNewOwner();

RecoveryRequest memory recoveryRequest = recoveryRequests[safeInEmail];
RecoveryConfig memory recoveryConfig = recoveryConfigs[safeInEmail];
if (recoveryRequest.executeAfter > 0) {
revert RecoveryAlreadyInitiated();
}
Expand All @@ -221,7 +207,7 @@ contract SafeZkEmailRecoveryPlugin is
uint256 threshold = getThreshold(safeInEmail);
if (recoveryRequests[safeInEmail].approvalCount >= threshold) {
uint256 executeAfter = block.timestamp +
recoveryConfigs[safeInEmail].recoveryDelay;
recoveryDelays[safeInEmail];

recoveryRequests[safeInEmail].executeAfter = executeAfter;

Expand Down Expand Up @@ -280,11 +266,7 @@ contract SafeZkEmailRecoveryPlugin is
}

/// @inheritdoc ISafeZkEmailRecoveryPlugin
function updateRecoveryConfig(
uint256 guardianCount,
uint256 threshold,
uint256 recoveryDelay
) external {
function updateRecoveryDelay(uint256 recoveryDelay) external {
// TODO: add implementation
}

Expand Down
27 changes: 3 additions & 24 deletions packages/plugins/src/safe/interface/ISafeZkEmailRecoveryPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,13 @@
pragma solidity ^0.8.0;

interface ISafeZkEmailRecoveryPlugin {
struct RecoveryConfig {
uint256 recoveryDelay; // the delay from the recovery request being initiated with enough appovals until it can be executed. Protects against malicious recovery attempts
}

struct RecoveryRequest {
uint256 executeAfter; // the timestamp from which the recovery request can be executed
address pendingNewOwner; // the pending new owner to be rotated
uint256 approvalCount; // number of guardian approvals for the recovery request
address ownerToSwap; // the old owner that will be swapped out for pendingNewOwner
}

struct SafeAccountInfo {
address safe;
address previousOwnerInLinkedList;
}

/** Errors */

/** TODO: */
Expand Down Expand Up @@ -100,14 +91,6 @@ interface ISafeZkEmailRecoveryPlugin {

/** Functions */

/**
* @notice Returns recovery config accociated with a safe address
* @param safe address to query storage with
*/
function getRecoveryConfig(
address safe
) external view returns (RecoveryConfig memory);

/**
* @notice Returns recovery request accociated with a safe address
* @param safe address to query storage with
Expand All @@ -117,10 +100,10 @@ interface ISafeZkEmailRecoveryPlugin {
) external view returns (RecoveryRequest memory);

/**
* @notice Returns the recovery router address that corresponds to the specified Safe account
* @notice Returns the recovery delay that corresponds to the specified Safe account
* @param safe address to query storage with
*/
function getRouterForSafe(address safe) external view returns (address);
function getRecoveryDelay(address safe) external view returns (uint256);

/**
* @notice Stores a recovery hash that can be used to recover a safe owner
Expand Down Expand Up @@ -160,11 +143,7 @@ interface ISafeZkEmailRecoveryPlugin {
function cancelRecovery() external;

// TODO: add natspec
function updateRecoveryConfig(
uint256 guardianCount,
uint256 threshold,
uint256 recoveryDelay
) external;
function updateRecoveryDelay(uint256 recoveryDelay) external;

// TODO: add natspec
function updateGuardian() external;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ contract SafeZkEmailRecoveryPlugin_Integration_Test is TestHelper {

SafeZkEmailRecoveryPlugin public safeZkEmailRecoveryPlugin;
Safe public safeSingleton;
Safe public safe;
Safe public safeAccount;
address public safeAddress;

address zkEmailDeployer = vm.addr(1);
Expand Down Expand Up @@ -95,10 +95,10 @@ contract SafeZkEmailRecoveryPlugin_Integration_Test is TestHelper {
owner = Alice.addr;
owners[0] = owner;

safe = Safe(payable(address(safeProxy)));
safeAddress = address(safe);
safeAccount = Safe(payable(address(safeProxy)));
safeAddress = address(safeAccount);

safe.setup(
safeAccount.setup(
owners,
1,
address(0),
Expand All @@ -113,7 +113,7 @@ contract SafeZkEmailRecoveryPlugin_Integration_Test is TestHelper {
);

vm.startPrank(safeAddress);
safe.enableModule(address(safeZkEmailRecoveryPlugin));
safeAccount.enableModule(address(safeZkEmailRecoveryPlugin));
vm.stopPrank();

guardian1 = safeZkEmailRecoveryPlugin.computeEmailAuthAddress(
Expand Down Expand Up @@ -149,7 +149,7 @@ contract SafeZkEmailRecoveryPlugin_Integration_Test is TestHelper {
function generateEmailAuthMsg() public {}

function acceptGuardian(
address safeAddress,
address safe,
address emailAccountRecoveryRouterAddress,
string memory subject,
bytes32 nullifier,
Expand All @@ -164,7 +164,7 @@ contract SafeZkEmailRecoveryPlugin_Integration_Test is TestHelper {

// Handle acceptance
bytes[] memory subjectParamsForAcceptance = new bytes[](1);
subjectParamsForAcceptance[0] = abi.encode(safeAddress);
subjectParamsForAcceptance[0] = abi.encode(safe);
EmailAuthMsg memory emailAuthMsg = EmailAuthMsg({
templateId: safeZkEmailRecoveryPlugin.computeAcceptanceTemplateId(
templateIdx
Expand All @@ -178,7 +178,7 @@ contract SafeZkEmailRecoveryPlugin_Integration_Test is TestHelper {
}

function handleRecovery(
address safeAddress,
address safe,
address newOwner,
address emailAccountRecoveryRouterAddress,
string memory subject,
Expand All @@ -195,7 +195,7 @@ contract SafeZkEmailRecoveryPlugin_Integration_Test is TestHelper {
bytes[] memory subjectParamsForRecovery = new bytes[](3);
subjectParamsForRecovery[0] = abi.encode(owner);
subjectParamsForRecovery[1] = abi.encode(newOwner);
subjectParamsForRecovery[2] = abi.encode(safeAddress);
subjectParamsForRecovery[2] = abi.encode(safe);

EmailAuthMsg memory emailAuthMsg = EmailAuthMsg({
templateId: safeZkEmailRecoveryPlugin.computeRecoveryTemplateId(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,15 +322,13 @@ contract SafeZkEmailRecoveryPluginTest is TestHelper {
ISafeZkEmailRecoveryPlugin.RecoveryRequest
memory recoveryRequest = safeZkEmailRecoveryPlugin
.getRecoveryRequest(safeAddress);
ISafeZkEmailRecoveryPlugin.RecoveryConfig
memory recoveryConfig = safeZkEmailRecoveryPlugin.getRecoveryConfig(
safeAddress
);
uint256 fetchedRecoveryDelay = safeZkEmailRecoveryPlugin
.getRecoveryDelay(safeAddress);

// Assert
assertEq(recoveryRequest.executeAfter, 0);
assertEq(recoveryRequest.pendingNewOwner, address(0));
assertEq(recoveryConfig.recoveryDelay, recoveryDelay);
assertEq(fetchedRecoveryDelay, recoveryDelay);
}

function test_configureRecovery_addMultipleRecoveryAccountsToSamePlugin()
Expand Down

0 comments on commit e450c20

Please sign in to comment.