The function isOperationDone(predecessor) only checks if the predecessor operation was executed.
However, if an operation is scheduled but later canceled, executeBatch() does not check if the predecessor was canceled.
This allows a malicious proposer to create fake dependencies that will never resolve, blocking execution indefinitely.
Attacker schedules an operation (Operation A) that acts as predecessor to another operation (Operation B).
They then schedule Operation B making it dependent on Operation A
Before executing, they cancel Operation A (which is not checked in executeBatch())
Operation B remains blocked forever because it is waiting for Operation A to be executed, but it was canceled instead.
This causes denial of service (DoS) for any operation that depends on the canceled predecessor.
The same issue in executeEmergencyAction()
Predecessor Verification bypass
Denial of Service (DoS)
Unresolved Dependencies
Manual Review
Modify isOperationDone() to include Canceled state
Example implementation:
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.