Нажмите ESC, чтобы закрыть

Shadow Governance в DeFi: Как найти скупку голосов On-Chain

Взлом управления в DeFi давно сместился из публичных тредов Discourse в анонимные пулы ликвидности и частные Telegram-чаты, где судьба миллиардов долларов решается за считанные блоки.

Прямая атака 51% на governance-протокол через покупку нативных токенов с рынка (например, UNI или AAVE) с экономической точки зрения бессмысленна: проскальзывание и стейкинг-модели сразу взвинтят цену токена до небес. Намного дешевле арендовать чужое право голоса через механизм Voter Bribes (взятки избирателям). Когда эта механика выносится за пределы прозрачных площадок вроде Votium или Hidden Hand и уходит во внебиржевые (OTC) сделки или закрытые смарт-контракты, возникает феномен Shadow Governance - скрытое управление, способное опустошить казначейство проекта или сменить параметры риска без ведома рядового комьюнити.

Анатомия теневого управления: От Curve Wars до анонимных пулов

Истоком индустрии взяток стала архитектура veTokenomics (vote-escrowed), разработанная Curve Finance. Залочив CRV на срок до 4 лет, пользователь получает veCRV, определяющий направление эмиссии токенов в пулы ликвидности. Проекты быстро поняли: вместо того чтобы выкупать CRV с рынка и морозить капитал на 4 года, дешевле платить еженедельный роялти владельцам veCRV за голосование за нужный пул.

Так появились публичные рынки взяток:

  • Votium (для экосистемы Convex/Curve)
  • Hidden Hand от Redacted Cartel (покрывает Balancer, Frax, Aura)

Однако официальные подкупы имеют критический изъян для крупных игроков - они публичны. Любой аналитик может открыть Dashboard и увидеть, кто и за какой пул платит.

В Shadow Governance используются совершенно иные механики:

  • Flashloans Governance Interception: Использование флешзаймов для мгновенного взятия под контроль протоколов без ve-блокировок. Атакующий берет заем, проводит предложение через мгновенный залог и сразу гасит долг.
  • Off-Chain / OTC Bribe Matching: Заключение сделок, где крупные институциональные держатели ve-токенов получают стейблкоины, альткоины или аллокации в будущих SAFT-контрактах на кастодиальные кошельки в обмен на голосование через делегирование.
  • Private Dark Pools (Wrapped Voting Power): Обертывание токенов управления в смарт-контракты, разделяющие экономическую ценность токена и его право голоса. Права на управление токенизируются и торгуются на аукционах слепого типа (Dutch Auctions).

Реальные кейсы: Как рушились протоколы из-за скрытого подкупа

Кейс 1: Атака на Beanstalk Farms (Апрель 2022) - $182 млн

Хотя формально это был взлом через Flashloan, корректнее назвать его «мгновенным теневым захватом управления». Атакующий взял флешзаим на $1 млрд в Lido stETH, Bean и других активах через Aave, получил свыше 70% голосов (Voting Power) в BIP-18 (Beanstalk Improvement Proposal) и моментально перевел себе все средства из казначейства.

В чем механика Shadow Governance: Протокол использовал мгновенный подсчет голосов на основе баланса токенов в текущем блоке без временной задержки (Timelock) и без требования предварительного стейкинга.

Кейс 2: Захват Tornado Cash Governance (Май 2023)

Атакующий опубликовал предложение, которое якобы использовало ту же логику, что и ранее одобренное предложение. Однако внутри предложения скрывался вредоносный код. Получив одобрение комьюнити, злоумышленник с помощью функции selfdestruct изменил логику контракта предложения на том же адресе (через CREATE2), начислил себе 1.2 млн фиктивных голосов TORN, получил полный контроль над DAO и вывел $2.1 млн из казначейства.

В чем механика Shadow Governance: Взломщик задействовал скрытые механизмы исполнения кода (metamorphic contracts), которые позволили обойти визуальный аудит proposals и подменить логику перед самым голосованием.

Как обнаружить Shadow Governance на уровне блокчейна

Отследить внебиржевую скупку голосов сложно, но внебиржевые договоренности всегда оставляют след прямо на блокчейне при исполнении. Аналитика строится на поиске аномалий в поведении крупных адресов (китов) и смарт-контрактов делегирования.

Сравнительный анализ легального и теневого подкупа

ПараметрПубличный Bribe (Votium / Hidden Hand)Shadow Governance (OTC / Private)
Прозрачность выплатОнчейн-распределение через Merkle TreeТранзакции через Tornado/Railgun/CEX или новые кошельки
Источник распределенияПубличные смарт-контракты рынкаЗакрытые мультисиги, EOAs, MEV-боты
ДелегированиеАвтоматизированное через мета-репозиторииРезкие, нетипичные смены делегатов перед голосованием
Экономическая выгодаОграничена рыночным ROI от эмиссииНепропорционально высокое вознаграждение за отдельный пункт
Таймлок (Timelock)Соблюдается базовыми правилами DAOИзбегается за счет создания экстренных мультисигов

Практический алгоритм поиска следов в блокчейне

Чтобы локализовать теневое управление, бэкенд-инженеры и аналитики настраивают отслеживание следующих аномалий:

  • Анализ паттернов делегирования (Delegate Tracking): Отслеживание события DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate). Если крупный адрес (топ-20 holders) передает право голоса на пустой кошелек за 2-3 блока до окончания voting window - это прямой маркер OTC-сделки.
  • Движение средств от Flash-Mixer контрактов: Если адрес, на который делегировали голоса, получает стейблкоины или native-токены от анонимных миксеров за несколько часов до голосования, с высокой долей вероятности идет процесс оплаты за исполнение конкретной воли заказчика.
  • Мемпул и MEV-подкуп (MEV-driven Voting): Захват предложения в самый последний блок. Атакующие засылают приватную транзакцию напрямую builder'у (через Flashbots), чтобы скрыть появление критической массы голосов до момента запечатывания блока.

Парсинг аномалий: Python-скрипт для мониторинга делегирования

Ниже представлен легкий скрипт на Python с использованием библиотеки web3.py, который отслеживает внезапную передачу крупных объемов voting power в ERC20Votes (Compound/OpenZeppelin архитектура) перед голосованиями.

import time
import logging
from collections import defaultdict
from web3 import Web3
# Настройка журналирования
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
# Защитный лаг от реорганизаций сети (12 блоков ~= 2.5 минуты)
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
w3 = Web3(Web3.HTTPProvider(RPC_URL))
if not w3.is_connected():
   raise ConnectionError("RPC недоступен. Проверьте API-ключ или работу ноды.")
# 2. Checksum и загрузка контракта
token_address = w3.to_checksum_address(RAW_TOKEN_ADDRESS)
contract = w3.eth.contract(address=token_address, abi=ABI)
# 3. Динамические параметры
try:
   TOKEN_DECIMALS = contract.functions.decimals().call()
   TOTAL_SUPPLY = contract.functions.totalSupply().call()
   logging.info(f"Токен загружен. Decimals: {TOKEN_DECIMALS} | Total Supply: {TOTAL_SUPPLY / (10 ** TOKEN_DECIMALS):,.0f}")
except Exception as e:
   logging.warning(f"Не удалось вычитать параметры токена, установлены дефолты: {e}")
   TOKEN_DECIMALS = 18
   TOTAL_SUPPLY = 1000000000 * (10 ** 18) # 1B по умолчанию
# Порог аномалии: 100,000 токенов
VOTE_THRESHOLD = 100000 * (10 ** TOKEN_DECIMALS)
def get_logs_batched(event_obj, from_block, to_block):
   """Безопасная вычитка логов батчами. Возвращает (logs, is_success)."""
   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"Сбой вычистки логов на блоках {start}-{end}: {e}")
           return [], False
   return all_events, True
def analyze_governance_shifts(from_block, to_block):
   """Аналитика движения голосов с расчетом доли от 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  # Ошибка при вычистке, блок НЕ смещаем!
   # Группировка нескольких событий DelegateChanged в рамках одной транзакции
   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
           
           # Расчет метрик относительно Total Supply
           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
           # Градация критичности
           severity = "КРИТИЧЕСКИЙ ВСПЛЕСК" if share_of_supply >= 1.0 else "ВНИМАНИЕ"
           logging.warning(f"[{severity}] Изменение Voting Power: {fmt_delta:+,.0f} токенов ({delta_share_of_supply:.3f}% от эмиссии)")
           logging.info(f"    Делегат: {delegate}")
           logging.info(f"    Итоговое влияние адреса: {fmt_new:,.0f} голосов ({share_of_supply:.3f}% от Total Supply)")
           logging.info(f"    Tx Hash: {tx_hash}")
           contexts = delegation_map.get(tx_hash, [])
           if contexts:
               logging.info(f"    Причина: ПРЯМАЯ СМЕНА ДЕЛЕГАТА ({len(contexts)} событий в Tx)")
               for ctx in contexts:
                   logging.info(f"      • Delegator: {ctx['delegator']} | {ctx['from']} -> {ctx['to']}")
           else:
               logging.info("    Причина: Изменение баланса у существующего делегата (Transfer / Claim / Mint / Burn)")
           
           print("-" * 75)
   return True
def start_realtime_monitoring(poll_interval=12):
   """Демон реального времени с удержанием глубины подтверждений."""
   latest_block = w3.eth.block_number
   last_processed_block = latest_block - SAFE_CONFIRMATIONS - 1
   logging.info(f"Запуск демона. Начальный безопасный блок: #{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("Диапазон не был полностью обработан из-за сбоя RPC. Повтор в следующем цикле.")
       except Exception as e:
           logging.error(f"Критический сбой в основном цикле: {e}")
       time.sleep(poll_interval)
if __name__ == "__main__":
   start_realtime_monitoring(poll_interval=12)

Как защититься от Shadow Governance

Рынок постепенно адаптируется к атакам на систему управления. Поверхностного аудита кода смарт-контракта уже недостаточно, требуется защитная архитектура самой модели DAO.

  • Внедрение Timelocks с функцией Veto: Изменения в коде не должны вступать в силу немедленно. Минимальная задержка в 48–72 часа дает возможность мультисигу безопасности (Security Council) заблокировать вредоносный proposal.
  • Переход на ve-модели с задержкой разблокировки: Если токены заблокированы без возможности быстрых манипуляций, стоимость проведения мгновенной теневой атаки возрастает кратно.
  • Оптимистическое управление (Optimistic Governance): Формат, внедренный Moonwell и Lido, где предложения принимаются по умолчанию, а голосование требуется только в том случае, если комьюнити желает наложить вето.
  • Dual-Token Governance: Разделение прав управления между держателями utility-токенов и поставщиками ликвидности / пользователями системы (как это реализовано в Lido через Dual Governance, где держатели stETH могут заблокировать решения LDO).

Теневое управление - естественное следствие превращения права голоса в финансовый актив. Задача аналитиков и блокчейн-инженеров EXMON - вовремя выявлять подобные аномалии в MEMpool и на уровне смарт-контрактов, обеспечивая абсолютную безопасность и прозрачность операций для участников нашей экосистемы.

Сделать краткую выжимку этой статьи с помощью:

FAQ

Shadow governance — это скрытый захват управления протоколом через частные внебиржевые (OTC) сделки, даркпулы или сторонние финансовые стимулы без прямых покупок governance-токенов на открытом рынке. Атакующие выплачивают вознаграждение крупным держателям ve-токенов или делегатам во внешних активах напрямую, минуя публичные маркетплейсы взяток, чтобы набрать необходимый кворум без проскальзывания цены и внимания комьюнити.

Для выявления подкупа парсят логи событий DelegateChanged и DelegateVotesChanged в смарт-контрактах, фиксируя аномальные сдвиги веса голосов и сопоставляя хэши транзакций с адресами инициаторов. Перекрестный анализ резких всплесков voting power с использованием приватных Flashbots-бандлов и входящими транзакциями из миксеров позволяет автоматическим скриптам изолировать скрытую концентрацию голосов до момента исполнения предложения.

Протоколы внедряют фиксацию права голоса по историческим снимкам блоков (historical snapshots), обязательные временные задержки исполнения (timelocks) с правом вето совета безопасности и динамические пороги кворума. Использование моделей оптимистичного управления и двухтокенных архитектур валидации полностью нейтрализует манипуляции через одноблочные Flashloans и делает краткосрочную аренду голосов экономически бессмысленной.
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.

...

Поделитесь своим мнением

Ваш e-mail не будет опубликован. Обязательные поля отмечены *