Overview
The contract defines:
But what is clear is , no function that checks user lock status, withdraw eligibility, or emergency flows ever references emergencyUnlockEnabled. For instance:
withdraw() checks whether the lock has expired.
emergencyWithdraw() checks if (block.timestamp < emergencyWithdrawDelay) revert.
No function includes a condition like if (emergencyUnlockEnabled) { /* skip normal checks */ }.
Hence, setting emergencyUnlockEnabled = true has no effect on user flows, meaning there is no special “unlock” triggered for locked tokens. The entire “emergency unlock” feature is effectively a no‐op.
Owner Schedules & Executes:
The owner calls:
The function sets emergencyUnlockEnabled = true.
No Actual Behavior Change:
A user with a locked position attempts an early unlock, expecting an “emergency unlock” path.
They find only normal rules in withdraw() or emergencyWithdraw()—the code never checks emergencyUnlockEnabled.
If the user’s lock isn’t expired, withdraw() reverts with LockNotExpired; if the user calls emergencyWithdraw() without waiting for enableEmergencyWithdraw(), it reverts with EmergencyWithdrawNotEnabled().
Conclusion: The user sees zero difference in flows from the emergencyUnlockEnabled flag.
False Sense of Security: Administrators or users may believe that scheduling and executing an “emergency unlock” will permit immediate user withdrawals. In reality, the code never references emergencyUnlockEnabled.
Incomplete Feature: The presence of scheduleEmergencyUnlock and executeEmergencyUnlock is misleading. It's an unused mechanism that can cause confusion in a real emergency.
Incorporate emergencyUnlockEnabled checks into lock rules or withdrawal functions, or
Remove the redundant scheduling/execution code if it’s no longer part of the design.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.