# Creating a new governance proposal can be prevented by anyone

Proposal ID is a hash of proposal data, so anyone can front-run a propose tx with identical data then cancel it, permanently blocking that proposal.

- Payout: Contest reward
- Severity: medium
- Program: Nouns Builder
- Credited: berndartmueller
- Disclosed: 2022-11-03
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-09-nouns-builder-findings/issues/182
- Library page: https://bugbountylibrary.com/r/c4%3A2022-09-nouns-builder%3AM-14
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:race-window vuln:business-logic vuln:governance

**Target:** Governor.propose / Governor.cancel governance contract
**Root cause:** proposalId is derived solely from proposal data (targets, values, calldatas, descriptionHash) with no proposer nonce, and cancel leaves voteStart non-zero so the PROPOSAL_EXISTS check still reverts on retry.
**Steps:**
1. Attacker observes victim's pending `propose(_targets,_values,_calldatas,_description)` tx in mempool.
2. Attacker front-runs with identical args; proposalId = hashProposal(...) is created with attacker as proposer.
3. Attacker immediately calls `cancel(proposalId)`; canceled=true but voteStart stays non-zero.
4. Victim's propose tx reverts with PROPOSAL_EXISTS(proposalId).
5. Repeat on any retry with same data; victim must alter description to get a new id.
**How found:** Code review of propose/cancel: noticed proposalId is a pure hash of proposal data and that cancel does not reset voteStart, so the existence check remains tripped after cancellation.
**Exploitation:** Requires attacker to hold enough voting weight to meet proposalThreshold to propose and be the proposer to cancel. Front-run propose with identical calldata, then cancel in same/next tx, griefing the DAO's governance by blocking legitimate proposals.
**Escalation:** Attacker can repeatedly spam front-run+cancel to persistently grief any proposer, as long as they retain proposer threshold balance.
**Insight:** When a proposal/order ID is a hash of user-supplied content, check whether a cancel/refund path leaves the existence marker set — that turns a griefing front-run into a permanent block; adding a per-sender nonce to the ID fixes it.
