Как через публичную keeper-функцию кастомного Safe-модуля и вредоносный хук Uniswap V4 из кошелька увели 2 900 rsETH — около $7,73 млн — одной атомарной транзакцией.
В двух предложениях. У жертвы на Safe (смарт-контрактный мультисиг) был установлен кастомный модуль-автоматизация, который управлял LP-позицией в Uniswap V4 и держал rsETH застейканным в Aave. У этого модуля была публичная keeper-функция, куда любой мог передать свои параметры — включая адрес пула и хука.
Атакующий заранее создал свой пул V4 с вредоносным хуком, затем дёрнул публичный keeper и заставил модуль, действуя от имени кошелька, вынуть rsETH из Aave и прогнать его через пул атакующего. Хук перехватил средства, а весь набор действий был упакован в один MEV-бандл и исполнен в том же блоке.
Все адреса публичны в блокчейне. Ниже — реконструкция ролей по ончейн-данным транзакции 0x0e7680…a705.
| Роль | Адрес | Что делает в атаке |
|---|---|---|
| Жертва | 0x40E93a52…D9f7AbA8 | Safe-кошелёк. Держал ~2 900 rsETH в виде aEthrsETH (застейкано в Aave V3). На нём висел уязвимый LP-модуль. |
| Атакующий | 0x0dC2c5D6…5dfe9b66 | Деплойер. 15.09 развернул связку вредоносных контрактов. Профинансирован через миксер RAILGUN — чтобы разорвать связь с источником средств. |
| Фейк-токен | 0x10605eE4…A0705Cb1 | Пустой ERC-20 «PAT», созданный атакующим только чтобы образовать вторую сторону пула V4 (rsETH ↔ PAT). |
| Получатель | 0xC70f00CD…8b80ea0 | Кошелёк, на который в итоге село ~2 882 rsETH (≈$7,43 млн) — чистая добыча после издержек. |
| MEV-исполнитель | 0x80BF7Db6…DBBD4e4 | Бот «Yoink», через который прошёл вызов yoink(). Заплатил билдеру блока (Ultrasound Money) ~18,9 ETH за гарантированное включение и порядок. |
| Инфраструктура | Uniswap V4 PoolManager · Aave V3 Pool · Permit2 | Легитимные протоколы, которые атака использовала как инструменты. Ни один из них не был «взломан». |
Safe — это не обычный кошелёк на приватном ключе, а смарт-контракт. Чтобы автоматизировать рутину (ребалансы, сбор наград, ролловер позиций), к нему подключают модули. Модуль — это доверенный контракт, который может двигать средства кошелька без подписи владельцев. В этом вся его польза и вся его опасность.
Вся атака — это одна связная последовательность, уложенная в один блок. Разберём её на четыре стадии: подготовка, «обман доверенного зама», извлечение и вывод.
Заранее, тем же днём, атакующий развернул три вещи: пустой токен-пустышку PAT, вредоносный хук и создал в Uniswap V4 пул, где одной стороной идёт rsETH, второй — PAT, а полем hooks в ключе пула указан его собственный хук.
Ключевой момент V4: пул однозначно определяется структурой PoolKey, в которую входит адрес хука. Кто задаёт PoolKey — тот выбирает, чей код будет исполняться во время операций с пулом.
Модуль жертвы имел публичную функцию-кипер (multicall), задуманную для ботов-автоматизаторов. Проблема: она принимала параметры от вызывающего — какой пул и какой хук использовать — и исполняла действие через DELEGATECALL в контексте самого Safe, без проверки, что цель разрешена.
Атакующий просто вызвал этот keeper и подсунул PoolKey со своим хуком. С этого момента полномочия кошелька оказались направлены на инфраструктуру атакующего. Это классический confused deputy — доверенного исполнителя заставляют применить его права против его же хозяина.
Дальше всё детерминировано. Модуль, действуя как кошелёк, погасил позицию в Aave: сжёг 2 900 aEthrsETH и получил 2 900 «живых» rsETH. Затем завёл их в пул V4 через unlock/swap. Пока пул исполнял операцию, он передал управление хуку атакующего в колбэках — и тот развёл расчёт (deltas) так, что rsETH вышел на сторону атакующего, а взамен кошелёк «получил» бесполезный PAT.
Всё это упаковано в один атомарный бандл и исполнено в блоке 25 980 525. Транзакция, которую вы видели, — это yoink() бота Yoink. Из 2 900 извлечённых rsETH около 2 882 rsETH (~$7,43 млн) село на кошелёк-получатель, а ~18,9 ETH ушло билдеру блока (Ultrasound Money) как плата за гарантированное включение и нужный порядок.
Ниже — упрощённая реконструкция дерева вызовов (не дословный трейс Etherscan, а его смысловая схема). Красным выделен опасный DELEGATECALL, из-за которого чужой код исполнился с полномочиями кошелька.
Схема, а не сырой лог. Настоящую транзакцию можно открыть по хешу 0x0e7680…a705 и посмотреть вкладки State и Internal Txns.
Ни Safe, ни Aave, ни Uniswap, ни сам протокол rsETH взломаны не были. Взломан был кастомный модуль — самая рискованная поверхность любого Safe, потому что модуль по определению обходит подписи владельцев.
1. Публичность. Keeper-функцию оставили открытой для всех (это нормально для киперов), но не ограничили, что она может делать.
2. Параметры извне. Адрес пула и хука брались из аргументов вызова, а не из зашитого белого списка.
3. Delegatecall. Действие исполнялось в контексте Safe, то есть чужой хук получал полный авторитет кошелька, а не свои собственные права.
Для тех, кто держит средства на Safe с кастомными модулями, или пишет такие модули. Каждый пункт закрывает одну из трёх ошибок выше.
Keeper должен ходить только по заранее зашитым PoolKey и адресам хуков. Параметр от вызывающего — только выбор из allowlist, а не произвольный адрес.
Если действие можно сделать обычным CALL с фиксированным получателем — так и делать. Delegatecall на код, который выбирает вызывающий, — почти всегда дыра.
Потолок на вывод за транзакцию, суточные лимиты, задержка на новые цели. Атака на $7,73 млн одним блоком не должна проходить без «стоп-крана».
Модуль должен иметь право трогать только конкретные токены и площадки, а не весь баланс кошелька. Aave-позиция не обязана быть доступна LP-модулю.
Ядро Safe проверено годами. Ваш самописный модуль — нет. Именно он расширяет поверхность атаки и требует ревью в первую очередь.
Системы вроде Blockaid ловят аномальные вызовы к модулям. В связке с circuit breaker это шанс остановить транзакцию до, а не констатировать после.
Прикладной вывод для P2P и приёма средств. Средства с этого взлома уже расходятся по цепочке переводов — через часы они могут оказаться на адресе, который пришлёт вам «обычный» платёж. Биржа увидит эту связь при первом же выводе. Проверяйте контрагента до приёма: @amlconsensus_bot — санкции, блэклисты эмитентов, метки и экспозиция по консенсусу источников, бесплатно.