13 марта 2023 года наша система обнаружила, что пул кредитования Euler Finance подвергся атаке с использованием флеш-кредита, что привело к убыткам в размере 197 миллионов долларов. Мы сначала оповестили сообщество, а затем провели анализ для определения первопричины.
1/ @eulerfinance is attacked. The root cause is due to the lack of liquidity check in the function donateToReserves()https://t.co/stWtPWK900
— BlockSec (@BlockSecTeam) March 13, 2023
See the detailed attack steps below. https://t.co/bm10OJHiXu pic.twitter.com/TDbYuzVWHe
Первопричина этого инцидента заключается в отсутствии проверки неплатёжеспособности в функции donateToReserves(). В частности, уязвимый контракт предоставляет пользователям возможность передавать своё обеспечение в протокол без проверки состоятельности позиции пользователя. Что ещё хуже, для избавления от этой проблемной позиции протокол предлагал ликвидаторам значительную скидку, позволяя погасить меньший долг при ликвидации. Злоумышленник создал крупную позицию и сделал её неплатёжеспособной, воспользовавшись этой функциональностью. Затем он смог выкупить своё обеспечение со скидкой и получить прибыль.
Предыстория
Обзор Euler Finance
Euler Finance — это протокол кредитования на Ethereum, позволяющий пользователям давать взаймы и занимать указанные токены. Когда кредиторы вносят средства в пул ликвидности Euler, им выпускается соответствующее количество EToken (приносящих доход токенов ERC20). Эти EToken можно обменять на внесённые базовые активы.
С другой стороны, заёмщики, получающие ликвидность, получают DToken. Эти DToken соответствуют стандарту ERC20 и не позволяют держателям самостоятельно их сжигать. В частности, вместо того чтобы позволять отправлять токены кому угодно, их может забрать кто угодно, но принятие требует согласия. С точки зрения базового актива заёмщики обязаны выплачивать проценты по своим займам, и часть этих процентов используется для покрытия безнадёжных долгов в протоколе.
Механизмы кредитования с плечом (также известного как самозаём) и мягкой ликвидации в Euler Finance являются двумя ключевыми концепциями, которые помогают лучше понять причину этой атаки.
Кредитование с плечом
Euler Finance предоставляет функцию кредитования с плечом, которая позволяет пользователям имитировать рекурсивную стратегию заимствования. Проще говоря, пользователи могут вносить обеспечение и выпускать EToken, которые затем можно использовать в качестве обеспечения для заимствования большего количества EToken. Контракт также выпускает соответствующее количество dToken в качестве долговых токенов. Состояние позиции пользователя рассчитывается на основе стоимости EToken и dToken. Согласно документации Euler Finance, пользователи могут использовать плечо до 19x. Функция кредитования с плечом сыграла ключевую роль в данном инциденте. Без этой функции злоумышленник не смог бы получить прибыль. С помощью кредитования с плечом злоумышленник увеличил размер своей позиции почти до 11x от первоначальной суммы, полученной из флеш-кредита.
Мягкая ликвидация
Как описано в официальном документе Euler Finance, механизм мягкой ликвидации позволяет ликвидаторам гибко помогать ликвидируемой стороне погашать долг, а не ограничиваться фиксированным коэффициентом ликвидации, как это принято в таких протоколах, как Compound и Aave. Мягкая ликвидация означает, что чем ниже состояние позиции, тем большая доля обеспечения подлежит ликвидации — до 75% в случае безнадёжного долга, согласно данным этого инцидента. Ликвидация значительно обесценённого обеспечения позволила злоумышленнику погасить флеш-кредит и получить прибыль.
Анализ уязвимости
Основная уязвимость, а именно отсутствие проверки неплатёжеспособности, существует в функции donateToReserves(), которая используется пользователями для передачи EToken из своих позиций в резерв протокола в виде пожертвований. Для обычных пользователей, как правило, нет стимула или мотивации выполнять такое действие. Действительно, уязвимость заключается в том, что функция donateToReserves() не выполняет проверку состояния при переводе EToken из пользовательских позиций. Это позволяет злоумышленникам напрямую жертвовать EToken из крупной позиции, созданной с помощью кредитования с плечом, что приводит к снижению состояния позиции ниже 100% и образованию безнадёжного долга.

Согласно замыслу, Euler Finance использует динамический коэффициент закрытия для «мягкой ликвидации» позиций. Проще говоря, чем хуже состояние позиции, тем выше доля обеспечения в этой позиции, которая может быть ликвидирована. В случае безнадёжного долга процент ликвидации может достигать 75% обеспечения в позиции (рассчитано на основе фактической транзакции атаки). В результате значительное количество ликвидируемого обесценённого обеспечения позволяет злоумышленнику погасить флеш-кредит и получить прибыль.
Анализ атаки
Существует несколько транзакций атаки, направленных на различные пулы:
- 0xc310a0affe2169d1f6feec1c63dbc7f7c62a887fa48795d327d4d2da2d6b111d (DAI)
- 0x71a908be0bef6174bccc3d493becdfd28395d8898e355d451cb52f7bac38617 (WBTC)
- 0x62bd3d31a7b75c098ccf28bc4d4af8c4a191b4b9e451fab4232258079e8b18c4 (wstETH)
- 0x465a6780145f1efe3ab52f94c006065575712d2003d83d85481f3d110ed13d9 (USDC)
- 0x3097830e9921e4063d334acb82f6a79374f76f0b1a8f857e89b89bc58df1f311 (stETH)
- 0x47ac3527d02e6b9631c77fad1cdee7bfa77a8a7bfd4880dccbda5146ace4088f (WETH)
Шаги атаки выглядят следующим образом (на примере первой транзакции атаки):
- Злоумышленник занял 30 млн DAI в AAVE через флеш-кредит.
- Злоумышленник внёс 20 млн DAI и получил обратно 20 млн eDAI.
- Поскольку Euler Finance предоставляет возможность кредитования с плечом, злоумышленник смог выпустить 195 млн eDAI и 200 млн dDAI. Теперь злоумышленник держит 215 млн eDAI и 200 млн dDAI.
- Продолжение вышесказанного. Был погашен долг в размере 10 млн, чтобы злоумышленник мог выпустить больше eDAI. Теперь злоумышленник держит 215 млн eDAI и 190 млн dDAI.
- Шаг 3 был повторён. Теперь злоумышленник держит 410 млн eDAI и 390 млн dDAI.
- Злоумышленник вызвал функцию donateToReserve для пожертвования 100 млн eDAI. Однако в процессе этого коэффициент состояния злоумышленника не проверялся. В этом случае позиция теперь может быть ликвидирована (310 млн eDAI против 390 млн dDAI), что даёт возможность получить прибыль.
- Злоумышленник ликвидировал позицию, используя контракт другого адреса в качестве ликвидатора (0xa0b3...). Ликвидатор (0xa0b3...) получил 310 млн eDAI и 259 млн dDAI.
- Злоумышленник сжёг 38,9 млн eDAI для вывода 38,9 млн DAI (больше вывести невозможно из-за проверок неплатёжеспособности) в позиции ликвидатора (0xa0b3...).
- Злоумышленник погасил флеш-кредит.
Ключевые шаги атаки 2–7 отмечены в трассировке транзакции.

Итоги
Это был крупнейший взлом 2023 года: рекордные 197 миллионов долларов были похищены 20-летним аргентинцем по имени Федерико Хайме, который предоставил СМИ «запутанный, местами противоречивый нарратив». Тем не менее «все восстанавливаемые средства» впоследствии были возвращены на адрес казначейства Euler Finance. Однако небольшая часть (около 200 тыс. долларов) была «непреднамеренно» отправлена группе Lazarus — предполагаемому спонсируемому государством северокорейскому преступному синдикату, находящемуся под санкциями Министерства финансов США. Подробную и интересную историю можно найти по этим ссылкам: ссылка 1 и ссылка 2.
Первопричиной этого инцидента стало отсутствие проверок неплатёжеспособности, что служит поучительным уроком. На самом деле для протокола кредитования крайне важно оценивать, следует ли внедрять проверки состояния позиции для любых процедур, которые могут повлиять на пользовательские позиции. Кроме того, команды проектов должны проактивно отслеживать свои протоколы кредитования на предмет значительных ликвидаций и создавать эффективные системы оповещения для своевременного обнаружения таких событий и реагирования на них.
Читайте другие статьи этой серии:
- Введение: Десять «выдающихся» инцидентов в сфере безопасности 2023 года
- №1: Сбор MEV-ботов через эксплуатацию уязвимостей в Flashbots Relay
- №3: Инцидент с KyberSwap: мастерская эксплуатация ошибок округления с исключительно тонкими вычислениями
- №4: Инцидент с Curve: ошибка компилятора порождает дефектный байткод из безобидного исходного кода
- №5: Platypus Finance: выживание в трёх атаках благодаря удаче
- №6: Инцидент с Hundred Finance: катализатор волны эксплойтов, связанных с точностью вычислений, в уязвимых форкнутых протоколах
- №7: Инцидент с ParaSpace: гонка со временем для предотвращения самой критической атаки в отрасли
- №8: Инцидент с SushiSwap: неловкая попытка спасения приводит к серии атак-подражаний
- №9: MEV-бот 0xd61492: от хищника к жертве в искусном эксплойте
- №10: Инцидент с ThirdWeb: несовместимость между доверенными модулями обнажает уязвимость



