DeFi-Specific Patterns: Governance, Bridges & L2 Risks (Hunter View)
A DeFi governance attack is usually not “smart people voted wrong.” It is temporary voting power, missing delay, or a message that was never authenticated — used to change outcomes or move funds. This Andrax tutorial — by Syed Zada Abrar — covers ~80% theory, ~20% report-reading lab.
Prerequisites: DeFi Flash Loan Attacks Explained; Oracle Manipulation in Smart Contracts; ERC-4626 Vault Security: Share Inflation & Donation Attacks; EIP-712 & Signature Replay; Proxy, UUPS & Storage Collision. Also useful: Hub; Spoke 01; Access Control Bugs.
Ethics fence: this spoke is report reading and checklist thinking. Study public post-mortems and primary docs. Do not probe live bridges, vote with flash-loan capital on mainnet, spam sequencers, or “confirm” a governance path against a live DAO. Immunefi rules ban mainnet and public-testnet testing of in-scope code. Lab = reading only.
Map: three trust surfaces hunters under-weight
| Surface | What hunters often miss | Typical impact class (Immunefi IVS, Smart Contracts) |
|---|---|---|
| Governance | Flash-loan votes without snapshot / delay; emergency paths | Critical includes “manipulation of governance voting result… resulting in a direct change” (IVS v2.3) |
| Bridges | Message auth, root defaults, upgrade-time init | Direct theft / unauthorized mint of bridged assets |
| L2 | Sequencer ordering, force-inclusion latency, messenger checks | Often out of scope as “sequencer downtime” on some bounty pages — still matters for design review (Sherlock validity criteria) |
| ERC-4337 (add-on) | Signature not bound to userOpHash / chainId / EntryPoint | Cross-chain or cross-EntryPoint replay (EIP-4337) |
Impact labels always follow the program’s in-scope list, not this table alone.
Governance — temporary power, permanent effect
OpenZeppelin-style Governors and custom DAOs share a pattern: who can propose, who can vote, when execution is allowed. A hunter checklist:
- Voting power source. Token balance at
block.number, checkpoint/snapshot, or livebalanceOf? Live balance + same-block flash liquidity is the Beanstalk-shaped failure. - Delay. Propose → vote → queue → execute. If
emergencyCommit(or equivalent) collapses the delay when a threshold is met, flash capital can finish the job in one transaction. - What execution can do. Can a successful proposal call an arbitrary target? Transfer treasury? Change roles? Upgrade a proxy? (UUPS / authorizeUpgrade belongs in that mental model.)
- Privileged paths. “Emergency” and “guardian” functions are access-control problems with governance branding (access control).
- Economic assumptions. Quorum that assumes “honest holders cannot be rented for one block” is an assumption, not a invariant.
Flash loans amplify. They are not the root bug. The root is missing time preference (snapshot or delay) between acquiring votes and executing irreversible effects. See flash loans.
Public post-mortem (governance): Beanstalk — REKT (18 April 2022). Pattern: flash-loan temporary voting power + malicious proposal + immediate emergencyCommit-style path. Read for the sequence and the missing delay, not for copy-paste txs. Dollar figures on rekt.news are that site’s reporting — do not invent new ones; quote only if you need them with the URL.
Bridges — authenticate the message, not the story
A bridge is a system that says “this event happened on chain A, so do X on chain B.” Hunters care about:
| Check | Failure mode |
|---|---|
| Who attests? | Single verifier / single DVN / undersigned guardian set |
| What is proven? | Merkle root, light-client, optimistic timeout, ZK proof |
| Default / zero values | Unset mapping entries that acceptableRoot-style logic treats as valid |
| Replay | Same message hash processable twice; missing nonce / processed flag |
| Upgrade / initialize | Init that pre-approves bytes32(0) or a trusted root incorrectly |
| Destination effect | Mint, unlock, or call arbitrary target on “verified” message |
Bridge replay attack explained (hunter sense): either (a) a message already processed is accepted again, or (b) a message that was never proven is treated as proven because of a default root / status. Nomad’s 2022 failure was closer to (b): unproven messages passed authentication after an upgrade-time initialization nuance.
Public post-mortem (bridge): Nomad Bridge — REKT (2 August 2022) for the incident narrative; Nomad’s own Root Cause Analysis for the Replica / acceptableRoot / confirmAt[bytes32(0)] mechanism. Lab = read both. Do not open a live Nomad (or any) bridge UI to “try” process.
When you file a bridge finding later: show the auth gap on a local fork / CTF / in-scope PoC rules, name the exact function, and map impact to the program’s IVS line (theft of bridged assets, unauthorized mint, etc.). No mainnet forge.
L2 — sequencer risk for smart-contract hunters
On optimistic and many ZK rollups, a sequencer orders transactions, soft-confirms them, and posts batches. Soft confirmation is not L1 finality. For contracts, that implies:
- Ordering / MEV. Liquidations and oracle-sensitive paths can be reordered within sequencer power.
- Censorship / delay. A user who must act in this window may need force-inclusion via L1 if the sequencer stalls or censors.
- Messenger footguns. L1↔L2 messages: verify
msg.senderis the messenger andxDomainMessageSender()is the expected L1 sender; account for address aliasing on OP Stack where documented. block.number/block.timestampsemantics differ by L2 — verify before porting L1 logic.
OP Stack public docs: Sequencer outages and Forced transaction. Read them as the L2 “primary source” for this lab: what users can do when the sequencer is unavailable, and what latency to expect. Track decentralization stage on L2BEAT without inventing TVL or stage counts in copy.
Bounty realism: Sherlock’s public validity list treats issues that rely on sequencers going offline or malfunctioning as invalid by default (criteria, item on sequencers). So “sequencer can censor me” is often a design assumption note for architects, not a paid Critical — unless the program explicitly scopes sequencer / centralized operator risk. Always read the program page.
ERC-4337 auditor pitfalls (compact)
EIP-4337 routes UserOperations through an EntryPoint. For auditors:
signatureMUST depend onchainidand theEntryPointaddress (spec anti-replay). Prefer validating the EntryPoint-provideduserOpHash, which already binds those fields — do not re-hash onlycallData.- Account:
validateUserOpmust gate on a trusted EntryPoint; other functions should be EntryPoint-gated (or self). - Paymaster: sponsorship checks in
validatePaymasterUserOpthat do not constrain execution /postOpinvite griefing or unintended sponsorship. - CREATE2 address symmetry is not free safety. Same address on two chains does not make a signature safe without chain binding.
- Bridges + AA: never assume
msg.senderon chain A equals the same person on chain B for AA wallets — destination address should be explicit.
This spoke does not ship an ERC-4337 lab. Treat the list as review prompts. Signature-domain thinking overlaps EIP-712 replay.
Lab — three public write-ups (reading only)
Goal: one note card each for governance, bridge, and L2. No Anvil fork of the incident. No mainnet calls.
| Slot | Source | Write five lines |
|---|---|---|
| Governance | Beanstalk — REKT | Voting power source; delay/emergency path; what execution moved; flash-loan role (amplifier); one hunter check you would add to a Governor review |
| Bridge | Nomad — REKT + Nomad RCA | Auth function; zero/default root behavior; upgrade/init role; why Watchers did not catch SC bug (per RCA); one PoC idea you would run only on a local toy Replica |
| L2 | OP Stack outages + Forced transaction | What force-inclusion is for; why soft confirm ≠ finality; one contract pattern that breaks if inclusion is delayed; whether a bounty would pay (check a real program’s OOS list later — do not spam) |
ILLUSTRATIVE note card template:
Incident / doc:
Root cause in one sentence:
Trust assumption that failed:
Would this be in-scope on a typical Immunefi SC program? (yes/no/depends — why)
Local-only follow-up I will NOT run on mainnet:
How hunters should report these classes later
- Governance: proposal id, voting power math, delay config, execution payload, local Governor PoC or unit test — not a live malicious BIP.
- Bridge: auth function, message bytes, why
acceptableRoot(or equivalent) returns true, processed-set behavior — local fork under program rules. - L2: distinguish protocol bug from documented sequencer assumption; cite program OOS before claiming Critical.
- ERC-4337: show
userOpHash/ domain binding gap with a local EntryPoint test.
Common hunter traps
| Trap | Better habit |
|---|---|
| “Flash loan = governance Critical” | Show missing snapshot/delay + executable impact |
| Replaying a historical bridge exploit live | Read post-mortem; PoC only local / scoped |
| Filing “sequencer can censor” as Critical everywhere | Read program OOS; Sherlock default invalidates many of these |
| Assuming AA address equals EOA across chains | Explicit destination + chain-bound signatures |
Skipping messenger xDomainMessageSender | Both checks, plus alias where the stack requires it |
Checklist before you call it a DeFi-structure bug
- Trust surface named (gov / bridge / L2 / AA)
- Time preference or auth primitive identified
- Impact mapped to program IVS (or marked design/OOS)
- Public write-up studied — not re-executed on mainnet
- Local follow-up (if any) stays on Anvil / CTF / in-scope fork rules
Next steps
- Prev (live): ERC-4626 Vault Security · EIP-712 Signature Replay · Flash Loans
- Live: Hub · Spoke 01
- Next (live): How to Write an Immunefi Bug Report That Gets Taken Seriously · Submitting to Immunefi, CodeHawks & Sherlock (2026 Workflow)
- Next (live): Your First Real Target: Public-Scope Workflow (Fork-Only Testing)
Educational content by Syed Zada Abrar for Andrax (andraxpentester.in). Authorized research only. Lab is public post-mortem / docs reading only — ILLUSTRATIVE study notes, not live probing.