Unsynchronized cancel functions in the Governance and the TimelockController
contracts allows any address with an EXECUTOR role to potentially execute cancelled proposals if they are already queued in the TimelockController
State Inconsistency Between Governance and TimelockContoller:
The issue stems from lack of interaction between the `cancel` functions in the `Governance` contract and the `TimelockController`.
If a proposal is canceled after being queued in timelock,
the governance contract updates its state as proposal.canceled = true ,
but the queued operation remains executable in `TimelockController`.
This leaves the possibility that the timelock operation could still be executed,
bypassing Governance's cancel flag.
Issue: The state() function in governance returns Canceled if `proposal.canceled == true` ,
preventing normal execution via the governance execute() function.
However, since the timelock’s internal state isn’t updated.
This disconnect might allow an operation to exist in the timelock
that doesn’t reflect the governance decision.
The design of Role based access control,
indicates that there could be other addresses with EXECUTOR roles
other than just the governance contract address.
Allowing any address with the EXECUTOR role to execute the previously cancelled proposal.
Inversely when a Queued proposal is cancelled in the TimelockController
it is currently NOT reflected in the Governance contract's _proposals[id].cancelled
Cancelled proposals can be executed by any EXECUTOR
if the proposal's currentState == Queued during cancellation.
Impact : High
Likelihood : Med
Here are two suggested methods to resolve the issue
Method 1 : Synchronize Governance and Timelock Cancellation
Modify the cancellation process in the Governance contract
so that when a proposal is canceled,
the corresponding scheduled operation in the Timelock is also canceled.
Method 2 : Disallow cancellation if the proposal is already queued in the Timelock.
i.e, when `currentState == ProposalState.Queued`
This prevents any inconsistencies by ensuring that queued proposals cannot be canceled.
Furthermore, On both cases
when a Queued proposal is cancelled in the TimelockController
it needs to be reflected thru a state update of _proposals[id].cancelled in the Governanace contract .
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.