Drücken Sie ESC, um zu schließen

Shadow Governance in DeFi: Voter Bribes On-Chain Aufspüren

Governance-Exploits im DeFi-Space haben sich längst von öffentlichen Discourse-Threads in anonyme Liquiditätspools und private Telegram-Gruppen verlagert. Wo früher Transparenz herrschte, wird das Schicksal von Milliardenbeträgen heute innerhalb weniger Blöcke besiegelt.

Ein direkter 51%-Angriff auf ein Governance-Protokoll durch das Aufkaufen von Native Tokens am Markt (wie UNI oder AAVE) ist ökonomisch völlig irrsinnig: Slippage und Staking-Mechanismen würden den Tokenpreis sofort durch die Decke jagen. Wesentlich günstiger ist es, fremde Stimmrechte über sogenannte Voter Bribes (Stimmkauf) anzumieten. Wenn dieses Playbook jedoch die transparenten Marktplätze wie Votium oder Hidden Hand verlässt und in OTC-Deals oder geschlossene Smart Contracts abwandert, entsteht Shadow Governance – eine verdeckte Einflussnahme, die das Projekt-Treasury leerraumen oder Risikoparameter klammheimlich ändern kann, bevor die Community überhaupt rafft, was abgeht.

Anatomie von Shadow Governance: Von den Curve Wars zu anonymen Dark Pools

Der Ursprung der Bribe-Industrie liegt in der von Curve Finance entwickelten veTokenomics (vote-escrowed). Wer CRV für bis zu 4 Jahre locked, erhält veCRV und bestimmt damit, wohin die Emissionen in den Liquiditätspools fließen. Andere Protokolle haben schnell kapiert: Statt selbst massenhaft CRV am Markt zu shoppen und Eigenkapital jahrelang einzufrieren, ist es weitaus billiger, veCRV-Holdern eine wöchentliche "Bribe" zu zahlen, damit sie für den eigenen Pool voten.

So entstanden offizielle Bribe-Märkte:

  • Votium (für das Convex/Curve-Ökosystem)
  • Hidden Hand von Redacted Cartel (deckt Balancer, Frax, Aura ab)

Öffentliche Bribe-Märkte haben für Wal-Akteure jedoch einen entscheidenden Haken: Sie sind komplett transparent. Jeder Analytics-Dev kann ein Dashboard öffnen und exakt nachvollziehen, wer wie viel Geld in welchen Pool pumpt.

Bei Shadow Governance kommen daher völlig andere Angriffsvektoren zum Einsatz:

  • Flashloan Governance Interception: Das Ausnutzen von Blitzkrediten, um Protokolle ohne ve-Lockup im Handumdrehen zu kapern. Der Angreifer leiht sich massive Stimmgewalt, drückt einen Antrag innerhalb eines einzigen Blocks durch und zahlt das Darlehen sofort wieder zurück.
  • Off-Chain / OTC Bribe Matching: Abgemachte Deals hinter verschlossenen Türen. Institutionelle ve-Holder kassieren Stablecoins, Altcoins oder künftige SAFT-Zuteilungen auf ihre Custodial Wallets – im Gegenzug delegieren sie ihre Stimmkraft zielgerichtet an den Käufer.
  • Private Dark Pools (Wrapped Voting Power): Das Verpacken von Governance-Tokens in Smart Contracts, um den ökonomischen Wert vom Stimmrecht zu entkoppeln. Das Stimmrecht wird tokenisiert und über verdeckte Versteigerungen (Dutch Auctions) gehandelt.

Real-World-Cases: Wie Protokolle durch verdeckte Votes gecrasht wurden

Case 1: Der Beanstalk Farms Exploit (April 2022) – $182 Mio. Schaden

Obwohl das Ganze formal als Flashloan-Attacke eingestuft wurde, war es im Kern eine „Instant Shadow Governance Feindübernahme“. Der Angreifer besorgte sich via Aave einen Flashloan über $1 Mrd. in Lido stETH, Bean und anderen Assets, sicherte sich damit über 70% Voting Power im BIP-18 (Beanstalk Improvement Proposal) und räumte die komplette Treasury in der gleichen Transaktion leer.

Die Shadow Governance Mechanik: Das Protokoll wertete Stimmen anhand der Token-Balance im aktuellen Block aus – ohne Timelock, ohne Staking-Lockup, ohne Sicherheitsnetz.

Case 2: Die feindliche Übernahme der Tornado Cash DAO (Mai 2023)

Der Angreifer reichte einen Governance-Antrag ein, der vorgeblich dieselbe Logik wie ein zuvor akzeptierter Proposal nutzte. Tief im Code versteckte sich jedoch ein böswilliger Exploit. Nachdem die Community grün gegeben hatte, nutzte der Hacker die Funktion selfdestruct, um die Logik des Contracts auf derselben Adresse (via CREATE2) auszutauschen. Er schaffte sich aus dem Nichts 1,2 Mio. gefälschte TORN-Stimmen, übernahm die volle Kontrolle über die DAO und zog $2,1 Mio. ab.

Die Shadow Governance Mechanik: Der Hacker nutzte verdeckte Mechanismen zur Code-Ausführung (Metamorphic Contracts). Damit hebelte er das visuelle Audit der Community aus und tauschte die Logik unmittelbar vor der Ausführung aus.

Wie man Shadow Governance auf Chain-Ebene aufspürt

Hinterzimmertreffen lassen sich zwar nicht direkt abfangen, doch sobald die Deals auf der Blockchain exekutiert werden, hinterlassen sie unweigerlich On-Chain-Spuren. Die Devs und Analysten konzentrieren sich dabei auf Anomalien im Verhalten von Wal-Wallets und Delegation-Contracts.

Vergleich: Legitime Bribes vs. Shadow Governance

ParameterÖffentliche Bribes (Votium / Hidden Hand)Shadow Governance (OTC / Private)
AuszahlungstransparenzOn-Chain-Verteilung via Merkle TreeTransaktionen über Tornado/Railgun/CEX oder frische Wallets
Herkunft der GelderÖffentliche Bribe-Marketplace-ContractsUnbekannte Multisigs, EOAs, MEV-Bots
Delegation PatternAutomatisiert über Meta-Registry-ContractsPlötzlicher, untypischer Wechsel von Delegaten kurz vor dem Vote
Ökonomische LogikGedeckelt durch den Markt-ROI der Token-EmissionenUnverhältnismäßig hohe Payouts für ein einzelnes Votum
Timelock-HandlingHält sich an die regulären Governance-Rules der DAOWird gezielt durch Emergency-Multisigs oder Exploit-Anträge umgangen

Praktischer Workflow zum On-Chain-Monitoring

Um Shadow Governance aufzudecken, setzen Backend-Engineers und Security-Analysten auf das Monitoring folgender Schlüssel-Signale:

  • Delegation Pattern Analysis (Delegate Tracking): Überwachung des Events DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate). Wenn eine Top-20-Whale-Adresse ihre Stimmkraft 2-3 Blöcke vor Ende der Voting-Phase auf ein leeres Wallet überträgt, ist das ein massives Red Flag für einen OTC-Deal.
  • Fund Flow aus Mixer-Contracts: Erhält die Wallet, an die Stimmen delegiert wurden, wenige Stunden vor dem Votum Stablecoins oder Native Tokens aus anonymen Mixern, riecht das stark nach Payout für ein gecauftes Votum.
  • Mempool & MEV-Driven Voting: Kaperung des Votings im allerletzten Block. Angreifer schleusen private Transaktionen direkt über Blockbuilder (z. B. via Flashbots) ein, damit die gebündelte Stimmkraft bis zum Inkludieren im Block unsichtbar bleibt.

Anomaly-Parser: Python-Script zur Überwachung von Delegation-Events

Hier ist ein schlankes Python-Skript auf Basis von web3.py, das plötzliche Shifts von Voting Power in ERC20Votes-Contracts (Compound/OpenZeppelin-Standard) im Auge behält.

import time
import logging
from collections import defaultdict
from web3 import Web3

# Logging-Setup
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")

RPC_URL = "https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"
RAW_TOKEN_ADDRESS = "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984" # UNI

# Sicherheitspuffer gegen Reorgs (12 Blöcke ~= 2.5 Minuten)
SAFE_CONFIRMATIONS = 12
BATCH_STEP = 1000

ABI = [
   {
       "inputs": [],
       "name": "decimals",
       "outputs": [{"type": "uint8"}],
       "stateMutability": "view",
       "type": "function"
   },
   {
       "inputs": [],
       "name": "totalSupply",
       "outputs": [{"type": "uint256"}],
       "stateMutability": "view",
       "type": "function"
   },
   {
       "anonymous": False,
       "inputs": [
           {"indexed": True, "name": "delegate", "type": "address"},
           {"indexed": False, "name": "previousBalance", "type": "uint256"},
           {"indexed": False, "name": "newBalance", "type": "uint256"}
       ],
       "name": "DelegateVotesChanged",
       "type": "event"
   },
   {
       "anonymous": False,
       "inputs": [
           {"indexed": True, "name": "delegator", "type": "address"},
           {"indexed": True, "name": "fromDelegate", "type": "address"},
           {"indexed": True, "name": "toDelegate", "type": "address"}
       ],
       "name": "DelegateChanged",
       "type": "event"
   }
]

# 1. RPC-Check
w3 = Web3(Web3.HTTPProvider(RPC_URL))
if not w3.is_connected():
   raise ConnectionError("RPC nicht erreichbar. API-Key oder Node-Status prüfen.")

# 2. Checksum & Contract-Init
token_address = w3.to_checksum_address(RAW_TOKEN_ADDRESS)
contract = w3.eth.contract(address=token_address, abi=ABI)

# 3. Dynamische Parameter
try:
   TOKEN_DECIMALS = contract.functions.decimals().call()
   TOTAL_SUPPLY = contract.functions.totalSupply().call()
   logging.info(f"Token geladen. Decimals: {TOKEN_DECIMALS} | Total Supply: {TOTAL_SUPPLY / (10 ** TOKEN_DECIMALS):,.0f}")
except Exception as e:
   logging.warning(f"Fehler beim Auslesen der Token-Parameter, verwende Defaults: {e}")
   TOKEN_DECIMALS = 18
   TOTAL_SUPPLY = 1000000000 * (10 ** 18) # Fallback: 1B

# Schwellenwert für Anomalien: 100.000 Token
VOTE_THRESHOLD = 100000 * (10 ** TOKEN_DECIMALS)

def get_logs_batched(event_obj, from_block, to_block):
   """Sicheres Auslesen von Logs in Batches. Liefert (logs, success_flag)."""
   all_events = []
   for start in range(from_block, to_block + 1, BATCH_STEP):
       end = min(start + BATCH_STEP - 1, to_block)
       try:
           logs = event_obj.get_logs(fromBlock=start, toBlock=end)
           all_events.extend(logs)
       except Exception as e:
           logging.error(f"Fehler beim Fetching der Logs für Blöcke {start}-{end}: {e}")
           return [], False
   return all_events, True

def analyze_governance_shifts(from_block, to_block):
   """Analysiert Shifts der Voting Power inklusive Anteil am Total Supply."""
   vote_changes, ok1 = get_logs_batched(contract.events.DelegateVotesChanged, from_block, to_block)
   delegations, ok2 = get_logs_batched(contract.events.DelegateChanged, from_block, to_block)
   
   if not (ok1 and ok2):
       return False  # Batch fehlgeschlagen, Blockzeiger NICHT weiterrücken!

   # Zuordnung mehrerer DelegateChanged-Events innerhalb derselben Transaktion
   delegation_map = defaultdict(list)
   for d in delegations:
       tx_hash = d.transactionHash.hex()
       delegation_map[tx_hash].append({
           "delegator": d.args.delegator,
           "from": d.args.fromDelegate,
           "to": d.args.toDelegate
       })

   for event in vote_changes:
       prev_bal = event.args.previousBalance
       new_bal = event.args.newBalance
       delta = new_bal - prev_bal

       if abs(delta) >= VOTE_THRESHOLD:
           tx_hash = event.transactionHash.hex()
           delegate = event.args.delegate
           
           # Berechnung der relativen Kennzahlen
           fmt_delta = delta / (10 ** TOKEN_DECIMALS)
           fmt_new = new_bal / (10 ** TOKEN_DECIMALS)
           share_of_supply = (new_bal / TOTAL_SUPPLY) * 100
           delta_share_of_supply = (abs(delta) / TOTAL_SUPPLY) * 100

           # Schweregrad bestimmen
           severity = "KRITISCHER SPIKE" if share_of_supply >= 1.0 else "WARNUNG"

           logging.warning(f"[{severity}] Voting Power Shift: {fmt_delta:+,.0f} Token ({delta_share_of_supply:.3f}% vom Total Supply)")
           logging.info(f"    Delegat: {delegate}")
           logging.info(f"    Gesamter Einfluss der Adresse: {fmt_new:,.0f} Stimmen ({share_of_supply:.3f}% vom Total Supply)")
           logging.info(f"    Tx Hash: {tx_hash}")

           contexts = delegation_map.get(tx_hash, [])
           if contexts:
               logging.info(f"    Ursache: DIREKTER DELEGATEN-WECHSEL ({len(contexts)} Events in Tx)")
               for ctx in contexts:
                   logging.info(f"      • Delegator: {ctx['delegator']} | {ctx['from']} -> {ctx['to']}")
           else:
               logging.info("    Ursache: Balance-Änderung beim bestehenden Delegaten (Transfer / Claim / Mint / Burn)")
           
           print("-" * 75)
   return True

def start_realtime_monitoring(poll_interval=12):
   """Realtime-Daemon mit fester Confirmation Depth."""
   latest_block = w3.eth.block_number
   last_processed_block = latest_block - SAFE_CONFIRMATIONS - 1

   logging.info(f"Daemon gestartet. Initialer sicherer Block: #{last_processed_block} (Confirmations = {SAFE_CONFIRMATIONS})")

   while True:
       try:
           current_block = w3.eth.block_number
           safe_block = current_block - SAFE_CONFIRMATIONS

           if safe_block > last_processed_block:
               success = analyze_governance_shifts(last_processed_block + 1, safe_block)
               if success:
                   last_processed_block = safe_block
               else:
                   logging.warning("Blockbereich aufgrund eines RPC-Fehlers nicht vollständig verarbeitet. Retry im nächsten Durchlauf.")
       except Exception as e:
           logging.error(f"Kritischer Fehler im Main-Loop: {e}")

       time.sleep(poll_interval)

if __name__ == "__main__":
   start_realtime_monitoring(poll_interval=12)

Defense Strategies gegen Shadow Governance

Der Markt entwickelt schrittweise Abwehrmechanismen gegen solche Governance-Attacks. Ein reines Audit des Smart-Contract-Codes reicht längst nicht mehr aus – das Systemdesign der DAO selbst muss gehärtet werden.

  • Implementation von Timelocks mit Veto-Funktion: Code-Änderungen dürfen niemals instant greifen. Ein Timelock von mindestens 48–72 Stunden verschafft dem Security Council die nötige Zeit, um bösartige Proposals vor der Execution zu stoppen.
  • Wechsel auf ve-Modelle mit Unstaking-Delay: Wenn Tokens fest gelockt sind und sich nicht blitzschnell verschieben lassen, steigen die Kosten für verdeckte Flash-Attacks um ein Vielfaches.
  • Optimistic Governance: Das Setup (u. a. von Moonwell und Lido genutzt), bei dem Anträge standardmäßig durchgehen und ein aktiver Vote nur nötig wird, wenn die Community explizit ein Veto einlegen will.
  • Dual-Token Governance: Die Aufteilung der Stimmrechte zwischen Utility-Token-Holdern und den eigentlichen Nutzern bzw. Liquidity Providern (wie bei Lidos Dual Governance, wo stETH-Holder Beschlüsse der LDO-Holder blockieren können).

Shadow Governance ist die logische Konsequenz daraus, dass Stimmrechte zum reinen Spekulationsgut werden. Für das Blockchain-Engineering und die Analytics-Teams bei EXMON hat es oberste Priorität, solche Anomalien im Mempool sowie auf Smart-Contract-Ebene frühzeitig zu erkennen, um maximale Sicherheit und volle Transparenz für unser Ökosystem zu gewährleisten.

Diesen Blogbeitrag zusammenfassen mit:

FAQ

Shadow Governance beschreibt die verdeckte Übernahme von Stimmrechten ohne den Kauf zugrundeliegender Governance-Token am offenen Markt über private OTC-Vereinbarungen, Dark Pools oder Off-Chain-Anreize. Angreifer umgehen öffentliche Bribe-Marktplätze und entschädigen große veToken-Halter oder Delegierte direkt mit externen Werten, um die erforderliche Stimmquote geräuschlos ohne Kursschwankungen oder Verdachtsmomente zu sichern.

Der Nachweis erfolgt durch das Auslesen der Smart-Contract-Events DelegateChanged und DelegateVotesChanged, um ungewöhnliche Stimmrechtsverlagerungen zu identifizieren und Transaktions-Hashes den ursprünglichen Delegierenden zuordnen zu können. Das Abgleichen plötzlicher Stimmrechtszuwächse mit privaten Flashbots-Bundles und Mittelzuflüssen aus Privacy-Mixern ermöglicht automatisierte Auswertungen vor der Ausführung von Beschlüssen.

Protokolle sichern ihre Governance durch die Nutzung historischer Block-Snapshots zur Stimmrechtsberechnung, zwingende Ausführungsverzögerungen (Timelocks) mit Veto-Rechten für Sicherheitsräte sowie dynamische Quorum-Schwellenwerte ab. Die Implementierung von Optimistic Governance und Dual-Token-Strukturen neutralisiert Single-Block-Flashloan-Manipulationsversuche und macht das kurzfristige Anmieten von Stimmrechten unrentabel.
Astra EXMON

Astra is the official voice of EXMON and the editorial collective dedicated to bringing you the most timely and accurate information from the crypto market. Astra represents the combined expertise of our internal analysts, product managers, and blockchain engineers.

...

Diskussion beitreten

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *