# Council veto protection does not work

GovernorAlpha veto check read function selectors from calldata instead of signatures, so the council could veto any proposal removing them and seize permanent DAO control.

- Payout: Audit contest
- Severity: high
- Program: Vader Protocol
- Found by: TomFrenchBlockchain
- Disclosed: 2022-05-03
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2021-12-vader-findings/issues/44
- Library page: https://bugbountylibrary.com/r/c4%3A2021-12-vader%3AH-13
- Tags: area:web3 domain:web3 impact:privesc kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic vuln:governance

**Target:** GovernorAlpha governance contract (Solidity)
**Root cause:** The veto function scanned proposal.calldatas for the changeCouncil selector, but selectors live in the signatures array and are only prepended by Timelock; the first 4 bytes of an ABI-encoded address are always zero, so the check never matched.
**Steps:**
1. Read GovernorAlpha.veto: it compares `proposal.calldatas[i]` against `this.changeCouncil.signature`.
2. Observe proposal struct stores function signature in `signatures[]` and only args in `calldatas[]`.
3. Note Timelock hashes the signature to derive the selector and prepends it to calldata at execution time.
4. Since calldata holds only an address argument, its first 4 bytes are zero and never equal the changeCouncil selector.
5. Council submits a proposal to changeCouncil and vetoes it, remaining in power indefinitely.
**How found:** Code review of the veto logic against the proposal struct layout and Timelock's selector derivation; noticed the selector is stored in signatures, not calldatas, so the comparison could never match.
**Exploitation:** A malicious council member proposes a changeCouncil action; because the veto check compares against calldata (always zero-prefixed) rather than the signature, the veto succeeds and the council cannot be removed by token holders, giving them absolute DAO control.
**Insight:** When a guard inspects calldata for a function selector, verify where the selector actually lives in that contract's proposal/execution model (signatures array vs calldata prefix) and that the compared value can ever equal the target selector.
