The execute() function in the Governance contract has dual behavior - it either queues or executes a proposal depending on the proposal state. This violates the principle of least surprise and can lead to user confusion, failed transactions, and gas losses.
The execute() function in Governance.sol has two different behaviors based on proposal state:
When a proposal succeeds, users need to:
Call execute() first time -> This queues the proposal
Wait for timelock delay
Call execute() again -> This actually executes the proposal
This dual behavior is not obvious from the function name or documentation.
Users may think their proposal executed when it only queued, leading to governance delays
Gas losses from failed second execute() calls if timelock hasn't passed
Integration errors with protocols expecting immediate execution
Confusion about actual proposal state
Poor user experience in governance participation
Manual review
Split the functionality into two explicit functions:
Add clear events and documentation about the two-phase execution process:
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.