Summary
When schedule a emergency action it takes 6 days to complete withdrawal of token. Here delay period is applied two places. To pass this modifier needs to wait 3 days . After that again need to wait another 3 days. It caused user to wait 6 days in total to withdraw funds.
Vulnerability Details
Owner calls a scheduleEmergencyAction , actionId as EMERGENCY_WITHDRAW_ACTION. Here _emergencyTimelock[actionId] is set to current timestamp.
function scheduleEmergencyAction(bytes32 actionId) external onlyOwner {
_emergencyTimelock[actionId] = block.timestamp;
emit EmergencyActionScheduled(actionId, block.timestamp + EMERGENCY_DELAY);
}
To pass this modifier it needs to wait 3 days
modifier withEmergencyDelay(bytes32 actionId) {
uint256 scheduleTime = _emergencyTimelock[actionId];
if (scheduleTime == 0) revert EmergencyActionNotScheduled();
if (block.timestamp < scheduleTime + EMERGENCY_DELAY) revert EmergencyDelayNotMet();
_;
delete _emergencyTimelock[actionId];
}
After 3 days Owner call enableEmergencyWithdraw
function enableEmergencyWithdraw() external onlyOwner withEmergencyDelay(EMERGENCY_WITHDRAW_ACTION) {
emergencyWithdrawDelay = block.timestamp + EMERGENCY_DELAY;
emit EmergencyWithdrawEnabled(emergencyWithdrawDelay);
}
Then to call this user need to wait another 3 days , meaning total in 6 days
function emergencyWithdraw() external nonReentrant {
if (emergencyWithdrawDelay == 0 || block.timestamp < emergencyWithdrawDelay)
revert EmergencyWithdrawNotEnabled();
Impact
EMERGENCY_DELAY is applied 2 times here to withdraw funds.
Tools Used
Manual Review
Recommendations
Remove delay applied here
function enableEmergencyWithdraw() external onlyOwner withEmergencyDelay(EMERGENCY_WITHDRAW_ACTION) {
emergencyWithdrawDelay = block.timestamp ;
emit EmergencyWithdrawEnabled(emergencyWithdrawDelay);
}