-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ackee audit fixes #22
Changes from all commits
4fd94ba
b31a844
06bf755
ba217b6
5f1fc9e
ad4fc63
9b235d8
184f5e5
b1811d4
8f3fa22
0e4234c
c9028df
f80edd7
bc1410a
8a4afd8
c8d8686
7dff8fc
c750719
51755ee
4c3a5bb
cd22e1f
142452a
2ec79b9
5ec1cfa
cef7751
397e64c
9c7db07
d24daeb
88371b8
5b26a9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,7 +59,7 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
/** | ||
* Deployer address stored to prevent frontrunning at initialization | ||
*/ | ||
address private deployer; | ||
address private immutable deployer; | ||
|
||
/** | ||
* Account address to recovery config | ||
|
@@ -82,19 +82,38 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
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, | ||
address _emailAuthImpl, | ||
address _subjectHandler | ||
) { | ||
if (_verifier == address(0)) { | ||
revert InvalidVerifier(); | ||
} | ||
if (_dkimRegistry == address(0)) { | ||
revert InvalidDkimRegistry(); | ||
} | ||
if (_emailAuthImpl == address(0)) { | ||
revert InvalidEmailAuthImpl(); | ||
} | ||
if (_subjectHandler == address(0)) { | ||
revert InvalidSubjectHandler(); | ||
} | ||
verifierAddr = _verifier; | ||
dkimAddr = _dkimRegistry; | ||
emailAuthImplementationAddr = _emailAuthImpl; | ||
subjectHandler = _subjectHandler; | ||
if (_subjectHandler == address(0)) { | ||
revert InvalidSubjectHandler(); | ||
} | ||
deployer = msg.sender; | ||
} | ||
|
||
|
@@ -108,16 +127,6 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
emailRecoveryModule = _emailRecoveryModule; | ||
} | ||
|
||
/** | ||
* @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(); | ||
} | ||
_; | ||
} | ||
|
||
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | ||
/* RECOVERY CONFIG, REQUEST AND TEMPLATE GETTERS */ | ||
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | ||
|
@@ -225,8 +234,8 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
* @param expiry The expiry time after which the recovery attempt is invalid | ||
*/ | ||
function configureRecovery( | ||
address[] memory guardians, | ||
uint256[] memory weights, | ||
address[] calldata guardians, | ||
uint256[] calldata weights, | ||
uint256 threshold, | ||
uint256 delay, | ||
uint256 expiry | ||
|
@@ -241,21 +250,17 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
revert SetupAlreadyCalled(); | ||
} | ||
|
||
if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToRecover(account)) { | ||
if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToBeRecovered(account)) { | ||
revert RecoveryModuleNotAuthorized(); | ||
} | ||
|
||
// Allow recovery configuration without configuring guardians | ||
if (guardians.length == 0 && weights.length == 0 && threshold == 0) { | ||
guardianConfigs[account].initialized = true; | ||
} else { | ||
(uint256 guardianCount, uint256 totalWeight) = | ||
setupGuardians(account, guardians, weights, threshold); | ||
} | ||
|
||
RecoveryConfig memory recoveryConfig = RecoveryConfig(delay, expiry); | ||
updateRecoveryConfig(recoveryConfig); | ||
|
||
emit RecoveryConfigured(account, guardians.length); | ||
emit RecoveryConfigured(account, guardianCount, totalWeight, threshold); | ||
} | ||
|
||
/** | ||
|
@@ -270,7 +275,7 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
{ | ||
address account = msg.sender; | ||
|
||
if (!guardianConfigs[account].initialized) { | ||
if (guardianConfigs[account].threshold == 0) { | ||
revert AccountNotConfigured(); | ||
} | ||
if (recoveryConfig.delay > recoveryConfig.expiry) { | ||
|
@@ -299,20 +304,18 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
* @param guardian The address of the guardian to be accepted | ||
* @param templateIdx The index of the template used for acceptance | ||
* @param subjectParams An array of bytes containing the subject parameters | ||
* @param {nullifier} Unused parameter. The nullifier acts as a unique identifier for an email, | ||
* but it is not required in this implementation | ||
*/ | ||
function acceptGuardian( | ||
address guardian, | ||
uint256 templateIdx, | ||
bytes[] memory subjectParams, | ||
bytes32 | ||
bytes32 /* nullifier */ | ||
) | ||
internal | ||
override | ||
{ | ||
if (templateIdx != 0) { | ||
revert InvalidTemplateIndex(); | ||
} | ||
|
||
address account = IEmailRecoverySubjectHandler(subjectHandler).validateAcceptanceSubject( | ||
templateIdx, subjectParams | ||
); | ||
|
@@ -321,7 +324,7 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
revert RecoveryInProcess(); | ||
} | ||
|
||
if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToRecover(account)) { | ||
if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToBeRecovered(account)) { | ||
revert RecoveryModuleNotAuthorized(); | ||
} | ||
|
||
|
@@ -333,6 +336,7 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
} | ||
|
||
guardiansStorage.updateGuardianStatus(account, guardian, GuardianStatus.ACCEPTED); | ||
guardianConfigs[account].acceptedWeight += guardianStorage.weight; | ||
|
||
emit GuardianAccepted(account, guardian); | ||
} | ||
|
@@ -348,27 +352,31 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
* @param guardian The address of the guardian initiating the recovery | ||
* @param templateIdx The index of the template used for the recovery request | ||
* @param subjectParams An array of bytes containing the subject parameters | ||
* @param {nullifier} Unused parameter. The nullifier acts as a unique identifier for an email, | ||
* but it is not required in this implementation | ||
*/ | ||
function processRecovery( | ||
address guardian, | ||
uint256 templateIdx, | ||
bytes[] memory subjectParams, | ||
bytes32 | ||
bytes32 /* nullifier */ | ||
) | ||
internal | ||
override | ||
{ | ||
if (templateIdx != 0) { | ||
revert InvalidTemplateIndex(); | ||
} | ||
|
||
(address account, bytes32 calldataHash) = IEmailRecoverySubjectHandler(subjectHandler) | ||
.validateRecoverySubject(templateIdx, subjectParams, address(this)); | ||
address account = IEmailRecoverySubjectHandler(subjectHandler).validateRecoverySubject( | ||
templateIdx, subjectParams, address(this) | ||
); | ||
|
||
if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToRecover(account)) { | ||
if (!IEmailRecoveryModule(emailRecoveryModule).isAuthorizedToBeRecovered(account)) { | ||
revert RecoveryModuleNotAuthorized(); | ||
} | ||
|
||
GuardianConfig memory guardianConfig = guardianConfigs[account]; | ||
if (guardianConfig.threshold > guardianConfig.acceptedWeight) { | ||
revert ThresholdExceedsAcceptedWeight(); | ||
} | ||
|
||
// This check ensures GuardianStatus is correct and also implicitly that the | ||
// account in email is a valid account | ||
GuardianStorage memory guardianStorage = getGuardian(account, guardian); | ||
|
@@ -380,16 +388,18 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
|
||
recoveryRequest.currentWeight += guardianStorage.weight; | ||
|
||
uint256 threshold = guardianConfigs[account].threshold; | ||
if (recoveryRequest.currentWeight >= threshold) { | ||
if (recoveryRequest.currentWeight >= guardianConfig.threshold) { | ||
bytes32 calldataHash = IEmailRecoverySubjectHandler(subjectHandler) | ||
.parseRecoveryCalldataHash(templateIdx, subjectParams); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this function separated from validateRecoverySubject to return calldataHash efficiently? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah it was a recommendation from the auditors to reduce unnecessary computation every time |
||
|
||
uint256 executeAfter = block.timestamp + recoveryConfigs[account].delay; | ||
uint256 executeBefore = block.timestamp + recoveryConfigs[account].expiry; | ||
|
||
recoveryRequest.executeAfter = executeAfter; | ||
recoveryRequest.executeBefore = executeBefore; | ||
recoveryRequest.calldataHash = calldataHash; | ||
|
||
emit RecoveryProcessed(account, executeAfter, executeBefore); | ||
emit RecoveryProcessed(account, guardian, executeAfter, executeBefore, calldataHash); | ||
} | ||
} | ||
|
||
|
@@ -409,7 +419,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 memory recoveryCalldata) public override { | ||
function completeRecovery(address account, bytes calldata recoveryCalldata) public override { | ||
if (account == address(0)) { | ||
revert InvalidAccountAddress(); | ||
} | ||
|
@@ -453,6 +463,9 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
* @dev Deletes the current recovery request associated with the caller's account | ||
*/ | ||
function cancelRecovery() external virtual { | ||
if (recoveryRequests[msg.sender].currentWeight == 0) { | ||
revert NoRecoveryInProcess(); | ||
} | ||
delete recoveryRequests[msg.sender]; | ||
emit RecoveryCancelled(msg.sender); | ||
} | ||
|
@@ -524,13 +537,15 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
*/ | ||
function setupGuardians( | ||
address account, | ||
address[] memory guardians, | ||
uint256[] memory weights, | ||
address[] calldata guardians, | ||
uint256[] calldata weights, | ||
uint256 threshold | ||
) | ||
internal | ||
returns (uint256, uint256) | ||
{ | ||
guardianConfigs.setupGuardians(guardiansStorage, account, guardians, weights, threshold); | ||
return | ||
guardianConfigs.setupGuardians(guardiansStorage, account, guardians, weights, threshold); | ||
} | ||
|
||
/** | ||
|
@@ -541,6 +556,12 @@ contract EmailRecoveryManager is EmailAccountRecovery, Initializable, IEmailReco | |
* @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); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If there are no changes for guardians, calldata is more appropriate than memory. Is that the reason this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, that is why they are now calldata?
Although I change them back in the consolidation PR as the function is called directly by the module. As they are abi decoded in
onInstall
, this means they are in memory so these params have to be changed back to memory. That is for the other PR though