Skip to content

Restrict proposal cancellation to the proposer - #181

Open
bergben wants to merge 2 commits into
mainfrom
feature/proposer-only-cancel
Open

bergben wants to merge 2 commits into
mainfrom
feature/proposer-only-cancel

Conversation

@bergben

@bergben bergben commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Executive Summary

  • cancel() guard reduced to msg.sender == proposal.proposer
  • Removes public branch that unlocked at proposerVotes < proposalThreshold
  • Affected 46 of 139 proposals to date; 45 executed, all still exposed 1 day past vote close
  • No storage change — layout-compatible implementation swap
  • Emergency de-queue path unchanged: Timelock.guardian is TEAM_MULTISIG
  • Compiles on solc 0.7.3; no test references cancel

Why the branch was reachable

Proposing power is a single 1,000,001 INST delegation rotated between the five
PROPOSER_AVO_MULTISIG addresses, none of which hold INST of their own. One delegation cannot
point at two addresses, so at most one multisig is above threshold at any time and the other four
are permanently below it. Every proposal whose proposer is not the current delegate was therefore
cancellable by any address, for gas, at any point before execution — cancel() excludes only
Executed, so Pending, Active, Succeeded and Queued were all open.

Raising the delegation buffer mitigates a single in-flight proposal but cannot cover two at once,
which is why this is fixed in code rather than operationally.

Deployment

Requires deploying a new implementation and an IGP calling _setImplementation(address) on the
Governor at 0x0204Cd037B2ec03605CFdFe482D8e257C765fA1B. Build with solc 0.7.3, optimizer enabled,
200 runs, matching hardhat.config.ts, so the runtime bytecode diff against the live
implementation isolates the cancel path for review.

Keep the delegation above threshold for the lifetime of that proposal — until it lands, the
upgrade proposal is itself cancellable under the behavior it removes.

Note on the G2 alternative

Compound's G2 whitelist does not address this. It retains the same permissionless branch for
non-whitelisted proposers and gates only whitelisted ones behind whitelistGuardian; its purpose
is to let sub-threshold accounts propose. Adopting it without whitelisting all five proposer
multisigs would change nothing here.

The public branch let any address cancel a proposal once the proposer's
voting power fell below proposalThreshold. Proposing power is a single
1,000,001 INST delegation rotated between five proposer multisigs, so that
condition holds for any proposal whose proposer is not the current delegate
— 46 of 139 to date. Timelock.guardian retains an emergency de-queue path
for queued proposals.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant