Skip to content

Commit

Permalink
Merge pull request #27 from zkemail/feat/additional-integration-tests
Browse files Browse the repository at this point in the history
Add additional integration tests
  • Loading branch information
JohnGuilding authored Aug 5, 2024
2 parents 32809e8 + b1485e4 commit 03f5547
Show file tree
Hide file tree
Showing 5 changed files with 629 additions and 206 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,21 +150,27 @@ contract EmailRecoveryManager_Integration_Test is
emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);
}

// function test_RevertWhen_HandleRecoveryCalled_AfterCompleteRecovery() public {
// acceptGuardian(accountAddress1, guardian1);
// acceptGuardian(accountAddress1, guardian2);
// vm.warp(12 seconds);
// handleRecovery(accountAddress1, guardian1, calldataHash1);
// handleRecovery(accountAddress1, guardian2, calldataHash1);
// vm.warp(block.timestamp + delay);
// emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1);

// EmailAuthMsg memory emailAuthMsg =
// getRecoveryEmailAuthMessage(accountAddress1, guardian1, calldataHash1);

// // vm.expectRevert("email nullifier already used"); // FIXME:
// emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);
// }
function test_HandleRecoveryCalled_AfterCompleteRecoveryStartsNewRecoveryRequest() public {
acceptGuardian(accountAddress1, guardians1[0]);
acceptGuardian(accountAddress1, guardians1[1]);
acceptGuardian(accountAddress1, guardians1[2]);
vm.warp(12 seconds);
handleRecovery(accountAddress1, guardians1[0], calldataHash1);
handleRecovery(accountAddress1, guardians1[1], calldataHash1);
vm.warp(block.timestamp + delay);
emailRecoveryModule.completeRecovery(accountAddress1, recoveryCalldata1);

IEmailRecoveryManager.RecoveryRequest memory recoveryRequest =
emailRecoveryModule.getRecoveryRequest(accountAddress1);
assertEq(recoveryRequest.currentWeight, 0);

EmailAuthMsg memory emailAuthMsg =
getRecoveryEmailAuthMessage(accountAddress1, guardians1[2], calldataHash1);

emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);
recoveryRequest = emailRecoveryModule.getRecoveryRequest(accountAddress1);
assertEq(recoveryRequest.currentWeight, 1);
}

function test_RevertWhen_CompleteRecoveryCalled_BeforeConfigureRecovery() public {
vm.prank(accountAddress1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { console2 } from "forge-std/console2.sol";
import { ModuleKitHelpers, ModuleKitUserOp } from "modulekit/ModuleKit.sol";
import { MODULE_TYPE_EXECUTOR, MODULE_TYPE_VALIDATOR } from "modulekit/external/ERC7579.sol";
import { EmailAuthMsg } from "ether-email-auth/packages/contracts/src/EmailAuth.sol";
import { SubjectUtils } from "ether-email-auth/packages/contracts/src/libraries/SubjectUtils.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.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";

Expand All @@ -15,6 +18,27 @@ import { OwnableValidatorRecovery_EmailRecoveryModule_Base } from "./EmailRecove
contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is
OwnableValidatorRecovery_EmailRecoveryModule_Base
{
using ModuleKitHelpers for *;
using Strings for uint256;

// Helper function
function executeRecoveryFlowForAccount(
address account,
address[] memory guardians,
bytes32 calldataHash,
bytes memory recoveryCalldata
)
internal
{
acceptGuardian(account, guardians[0]);
acceptGuardian(account, guardians[1]);
vm.warp(block.timestamp + 12 seconds);
handleRecovery(account, guardians[0], calldataHash);
handleRecovery(account, guardians[1], calldataHash);
vm.warp(block.timestamp + delay);
emailRecoveryModule.completeRecovery(account, recoveryCalldata);
}

function setUp() public override {
super.setUp();
}
Expand Down Expand Up @@ -68,102 +92,183 @@ contract OwnableValidatorRecovery_EmailRecoveryModule_Integration_Test is
assertEq(updatedOwner, newOwner1);
}

// function test_Recover_CannotMixAccountHandleAcceptance() public {
// acceptGuardian(accountAddress1, guardians1[0]);
// acceptGuardian(accountAddress2, guardians2[1]);
// vm.warp(12 seconds);
// handleRecovery(accountAddress1, guardians1[0], calldataHash1);

// EmailAuthMsg memory emailAuthMsg = getRecoveryEmailAuthMessage(
// accountAddress1,
// guardians1[1],
// calldataHash1
// );

// vm.expectRevert(
// abi.encodeWithSelector(
// IEmailRecoveryManager.InvalidGuardianStatus.selector,
// GuardianStatus.REQUESTED,
// GuardianStatus.ACCEPTED
// )
// );
// emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);
// }

// function test_Recover_CannotMixAccountHandleRecovery() public {
// acceptGuardian(accountAddress1, guardians1[0]);
// acceptGuardian(accountAddress1, guardians1[1]);
// vm.warp(12 seconds);
// handleRecovery(accountAddress1, guardians1[0], calldataHash1);

// EmailAuthMsg memory emailAuthMsg = getRecoveryEmailAuthMessage(
// accountAddress2,
// guardians1[1],
// calldataHash2
// );

// vm.expectRevert(
// abi.encodeWithSelector(
// IEmailRecoveryManager.InvalidGuardianStatus.selector,
// GuardianStatus.REQUESTED,
// GuardianStatus.ACCEPTED
// )
// );
// emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);
// }
function test_Recover_RevertWhen_MixAccountHandleAcceptance() public {
acceptGuardian(accountAddress1, guardians1[0]);
acceptGuardianWithAccountSalt(accountAddress2, guardians1[1], accountSalt2);
vm.warp(12 seconds);

// Helper function
function executeRecoveryFlowForAccount(
address account,
bytes32 calldataHash,
bytes memory recoveryCalldata
)
internal
{
acceptGuardian(account, guardians1[0]);
acceptGuardian(account, guardians1[1]);
EmailAuthMsg memory emailAuthMsg =
getRecoveryEmailAuthMessage(accountAddress1, guardians1[1], calldataHash1);

vm.expectRevert("guardian is not deployed");
emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);

emailAuthMsg = getRecoveryEmailAuthMessage(accountAddress1, guardians1[0], calldataHash1);

vm.expectRevert(
abi.encodeWithSelector(
IEmailRecoveryManager.ThresholdExceedsAcceptedWeight.selector, 3, 1
)
);
emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);
}

function test_Recover_RevertWhen_MixAccountHandleRecovery() public {
acceptGuardianWithAccountSalt(accountAddress2, guardians1[1], accountSalt2);

acceptGuardian(accountAddress1, guardians1[0]);
acceptGuardian(accountAddress1, guardians1[1]);
vm.warp(block.timestamp + 12 seconds);
handleRecovery(account, guardians1[0], calldataHash);
handleRecovery(account, guardians1[1], calldataHash);
handleRecovery(accountAddress1, guardians1[0], calldataHash1);

EmailAuthMsg memory emailAuthMsg = getRecoveryEmailAuthMessageWithAccountSalt(
accountAddress2, guardians1[1], calldataHash2, accountSalt2
);

vm.expectRevert(
abi.encodeWithSelector(
IEmailRecoveryManager.ThresholdExceedsAcceptedWeight.selector,
uint256(3),
uint256(2)
)
);
emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);
}

function test_Recover_RevertWhen_UninstallModuleBeforeAnyGuardiansAccepted() public {
instance1.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, "");

EmailAuthMsg memory emailAuthMsg =
getAcceptanceEmailAuthMessage(accountAddress1, guardians1[0]);

vm.expectRevert(
abi.encodeWithSelector(
IEmailRecoveryManager.InvalidGuardianStatus.selector,
uint256(GuardianStatus.NONE),
uint256(GuardianStatus.REQUESTED)
)
);
emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx);
}

function test_Recover_RevertWhen_UninstallModuleBeforeEnoughAcceptedAndTryHandleAcceptance()
public
{
acceptGuardian(accountAddress1, guardians1[0]);
instance1.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, "");

EmailAuthMsg memory emailAuthMsg =
getAcceptanceEmailAuthMessage(accountAddress1, guardians1[1]);

vm.expectRevert(
abi.encodeWithSelector(
IEmailRecoveryManager.InvalidGuardianStatus.selector,
uint256(GuardianStatus.NONE),
uint256(GuardianStatus.REQUESTED)
)
);
emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx);
}

function test_Recover_RevertWhen_UninstallModuleAfterEnoughAcceptedAndTryHandleRecovery()
public
{
acceptGuardian(accountAddress1, guardians1[0]);
acceptGuardian(accountAddress1, guardians1[1]);
vm.warp(12 seconds);

EmailAuthMsg memory emailAuthMsg =
getRecoveryEmailAuthMessage(accountAddress1, guardians1[0], calldataHash1);

instance1.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, "");
vm.expectRevert(
abi.encodeWithSelector(
IEmailRecoveryManager.InvalidGuardianStatus.selector,
uint256(GuardianStatus.NONE),
uint256(GuardianStatus.ACCEPTED)
)
);
emailRecoveryModule.handleRecovery(emailAuthMsg, templateIdx);
}

function test_Recover_RevertWhen_UninstallModuleAfterOneApprovalAndTryHandleRecovery() public {
acceptGuardian(accountAddress1, guardians1[0]);
acceptGuardian(accountAddress1, guardians1[1]);
vm.warp(12 seconds);
handleRecovery(accountAddress1, guardians1[0], calldataHash1);

vm.startPrank(accountAddress1);
vm.expectRevert(IGuardianManager.RecoveryInProcess.selector);
emailRecoveryModule.onUninstall("");
}

function test_Recover_RevertWhen_UninstallModuleProcessRecoveryAndTryCompleteRecovery()
public
{
acceptGuardian(accountAddress1, guardians1[0]);
acceptGuardian(accountAddress1, guardians1[1]);
vm.warp(12 seconds);
handleRecovery(accountAddress1, guardians1[0], calldataHash1);
handleRecovery(accountAddress1, guardians1[1], calldataHash1);
vm.warp(block.timestamp + delay);
emailRecoveryModule.completeRecovery(account, recoveryCalldata);

vm.startPrank(accountAddress1);
vm.expectRevert(IGuardianManager.RecoveryInProcess.selector);
emailRecoveryModule.onUninstall("");
}

// function test_Recover_RotatesMultipleOwnersSuccessfully() public {
// executeRecoveryFlowForAccount(
// accountAddress1,
// calldataHash1,
// recoveryCalldata1
// );
// vm.warp(block.timestamp + 12 seconds);
// executeRecoveryFlowForAccount(
// accountAddress2,
// calldataHash2,
// recoveryCalldata2
// );
// vm.warp(block.timestamp + 12 seconds);
// executeRecoveryFlowForAccount(
// accountAddress3,
// calldataHash3,
// recoveryCalldata3
// );

// address updatedOwner1 = validator.owners(accountAddress1);
// address updatedOwner2 = validator.owners(accountAddress2);
// address updatedOwner3 = validator.owners(accountAddress3);
// assertEq(updatedOwner1, newOwner1);
// assertEq(updatedOwner2, newOwner2);
// assertEq(updatedOwner3, newOwner3);
// }

// function test_Recover_RevertWhen_InvalidTimestamp() public {
// acceptGuardian(accountAddress1, guardians1[0]);
// EmailAuthMsg memory emailAuthMsg = getAcceptanceEmailAuthMessage(
// accountAddress2,
// guardians2[0]
// );

// vm.expectRevert("invalid timestamp");
// emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx);
// }
function test_Recover_RevertWhen_UninstallModuleAndTryRecoveryAgain() public {
executeRecoveryFlowForAccount(accountAddress1, guardians1, calldataHash1, recoveryCalldata1);
address updatedOwner1 = validator.owners(accountAddress1);
assertEq(updatedOwner1, newOwner1);

instance1.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, "");

EmailAuthMsg memory emailAuthMsg =
getAcceptanceEmailAuthMessage(accountAddress1, guardians1[0]);

vm.expectRevert(
abi.encodeWithSelector(
IEmailRecoveryManager.InvalidGuardianStatus.selector,
uint256(GuardianStatus.NONE),
uint256(GuardianStatus.REQUESTED)
)
);
emailRecoveryModule.handleAcceptance(emailAuthMsg, templateIdx);
}

function test_Recover_UninstallModuleAndRecoverAgain() public {
executeRecoveryFlowForAccount(accountAddress1, guardians1, calldataHash1, recoveryCalldata1);
address updatedOwner = validator.owners(accountAddress1);
assertEq(updatedOwner, newOwner1);

instance1.uninstallModule(MODULE_TYPE_EXECUTOR, recoveryModuleAddress, "");
instance1.installModule({
moduleTypeId: MODULE_TYPE_EXECUTOR,
module: recoveryModuleAddress,
data: abi.encode(isInstalledContext, guardians1, guardianWeights, threshold, delay, expiry)
});

bytes memory newRecoveryCalldata = abi.encodeWithSelector(functionSelector, newOwner2);
bytes32 newCalldataHash = keccak256(newRecoveryCalldata);
executeRecoveryFlowForAccount(
accountAddress1, guardians1, newCalldataHash, newRecoveryCalldata
);

updatedOwner = validator.owners(accountAddress1);
assertEq(updatedOwner, newOwner2);
}

function test_Recover_RotatesMultipleOwnersSuccessfully() public {
executeRecoveryFlowForAccount(accountAddress1, guardians1, calldataHash1, recoveryCalldata1);
executeRecoveryFlowForAccount(accountAddress2, guardians2, calldataHash2, recoveryCalldata2);
executeRecoveryFlowForAccount(accountAddress3, guardians3, calldataHash3, recoveryCalldata3);

address updatedOwner1 = validator.owners(accountAddress1);
address updatedOwner2 = validator.owners(accountAddress2);
address updatedOwner3 = validator.owners(accountAddress3);
assertEq(updatedOwner1, newOwner1);
assertEq(updatedOwner2, newOwner2);
assertEq(updatedOwner3, newOwner3);
}
}
Loading

0 comments on commit 03f5547

Please sign in to comment.