Один нуль — $10 миллионов убытков. Протокол Resupply попался на арифметике
NewsMakerЧто скрывает атака на Resupply за ширмой 'простой' ошибки?
Криптовалютный проект Resupply оказался в центре киберинцидента из-за сложного эксплойта, который позволил злоумышленнику создать долговую дыру в размере 10 миллионов reUSD. Атака затронула лишь одну конкретную торговую пару — crvUSD-wstUSR, что, по словам команды, не повлияло на остальные элементы экосистемы.
Проблема возникла в логике, связанной с обработкой залогов и расчётом обменного курса. В основе работы Resupply лежит модель CDP (кредитов под залог), где залогом служат токены стандарта ERC-4626, в данном случае — доли из CurveLend и FraxLend. Для оценки стоимости залога используются оракулы, полагающиеся на функцию convertToAssets(), которая конвертирует доли в базовые активы, принимая crvUSD и frxUSD за эквивалентные reUSD.
Ключевую роль в атаке сыграло то, что Curvelend-вольт, лежащий в основе пары crvUSD-wstUSR, на момент инцидента был полностью пуст. Этим и воспользовался злоумышленник. Сначала он перевёл 2000 crvUSD на контроллер вольта — это адрес, управляющий активами вольта. После этого он внёс всего 2 crvUSD, за которые получил минимальное количество долей — 1 wei.
На первый взгляд, такая манипуляция могла показаться безобидной, поскольку оракул продолжал корректно отслеживать реальную стоимость долей. Однако атака была продумана до мелочей и выходила за рамки стандартной схемы «инфляции» долей.
Суть заключалась в особенностях расчёта обменного курса внутри смарт-контракта. При определении стоимости долей использовалась жёстко заданная величина в 1e18 долей, которая через convertToAssets() возвращала завышенное значение — 2e36. Далее по коду происходил математический расчёт:
exchangeRate = 1e36 / 2e36
Эта операция из-за особенностей округления EVM сводилась к нулю. Хотя на первый взгляд обменный курс, равный нулю, не кажется критичным, именно это стало основой для успешного обхода проверки платёжеспособности при оформлении займа.
Во время каждого запроса на заём контракт выполняет проверку:
_isSolvent() ➔ ltv = (_borrowAmount * exchangeRate * LTV_PRECISION) / EXCHANGE_PRECISION / _collateralAmount
Из-за того что exchangeRate стал равен нулю, итоговое значение ltv (отношение суммы займа к залогу) также становилось нулевым, что позволяло системе считать пользователя всегда платёжеспособным, вне зависимости от реального положения дел.
Благодаря этому атакующий смог занять всю доступную сумму — 10 миллионов reUSD — в рамках лимита по этой паре.
После выявления инцидента команда Resupply оперативно приняла ряд мер. Проблемная пара была остановлена, а лимит задолженности установлен на нулевое значение. Дополнительно временно заблокированы выводы из страхового пула, который служит для покрытия убытков по всем торговым парам.
Чтобы исключить дальнейшие подобные атаки, разработчики ввели новую логику расчёта процентной ставки по этой паре, установив её на нулевом уровне, что исключает накопление дополнительных долгов. Также задействован специальный контракт для сжигания долей, который призван нейтрализовать аналогичные уязвимости во всей системе.
По словам представителей проекта, общая сумма убытков была частично покрыта за счёт средств казначейства Resupply — на данный момент уже возвращено более 643 тысяч reUSD. Оставшиеся украденные средства продолжают отслеживаться на блокчейне, команда заявляет, что ситуация находится под полным контролем.
Для разблокировки страхового пула и окончательного урегулирования последствий предстоит провести формальное голосование среди держателей токенов. Также в ближайшее время будут обновлены ключевые компоненты системы ResupplyPairCore.sol и ResupplyPairDeployer.sol, что должно навсегда устранить возможность подобной атаки.
Команда призывает всех участников сообщества следить за новостями и обновлениями через официальные форумы управления проектом.

Криптовалютный проект Resupply оказался в центре киберинцидента из-за сложного эксплойта, который позволил злоумышленнику создать долговую дыру в размере 10 миллионов reUSD. Атака затронула лишь одну конкретную торговую пару — crvUSD-wstUSR, что, по словам команды, не повлияло на остальные элементы экосистемы.
Проблема возникла в логике, связанной с обработкой залогов и расчётом обменного курса. В основе работы Resupply лежит модель CDP (кредитов под залог), где залогом служат токены стандарта ERC-4626, в данном случае — доли из CurveLend и FraxLend. Для оценки стоимости залога используются оракулы, полагающиеся на функцию convertToAssets(), которая конвертирует доли в базовые активы, принимая crvUSD и frxUSD за эквивалентные reUSD.
Ключевую роль в атаке сыграло то, что Curvelend-вольт, лежащий в основе пары crvUSD-wstUSR, на момент инцидента был полностью пуст. Этим и воспользовался злоумышленник. Сначала он перевёл 2000 crvUSD на контроллер вольта — это адрес, управляющий активами вольта. После этого он внёс всего 2 crvUSD, за которые получил минимальное количество долей — 1 wei.
На первый взгляд, такая манипуляция могла показаться безобидной, поскольку оракул продолжал корректно отслеживать реальную стоимость долей. Однако атака была продумана до мелочей и выходила за рамки стандартной схемы «инфляции» долей.
Суть заключалась в особенностях расчёта обменного курса внутри смарт-контракта. При определении стоимости долей использовалась жёстко заданная величина в 1e18 долей, которая через convertToAssets() возвращала завышенное значение — 2e36. Далее по коду происходил математический расчёт:
exchangeRate = 1e36 / 2e36
Эта операция из-за особенностей округления EVM сводилась к нулю. Хотя на первый взгляд обменный курс, равный нулю, не кажется критичным, именно это стало основой для успешного обхода проверки платёжеспособности при оформлении займа.
Во время каждого запроса на заём контракт выполняет проверку:
_isSolvent() ➔ ltv = (_borrowAmount * exchangeRate * LTV_PRECISION) / EXCHANGE_PRECISION / _collateralAmount
Из-за того что exchangeRate стал равен нулю, итоговое значение ltv (отношение суммы займа к залогу) также становилось нулевым, что позволяло системе считать пользователя всегда платёжеспособным, вне зависимости от реального положения дел.
Благодаря этому атакующий смог занять всю доступную сумму — 10 миллионов reUSD — в рамках лимита по этой паре.
После выявления инцидента команда Resupply оперативно приняла ряд мер. Проблемная пара была остановлена, а лимит задолженности установлен на нулевое значение. Дополнительно временно заблокированы выводы из страхового пула, который служит для покрытия убытков по всем торговым парам.
Чтобы исключить дальнейшие подобные атаки, разработчики ввели новую логику расчёта процентной ставки по этой паре, установив её на нулевом уровне, что исключает накопление дополнительных долгов. Также задействован специальный контракт для сжигания долей, который призван нейтрализовать аналогичные уязвимости во всей системе.
По словам представителей проекта, общая сумма убытков была частично покрыта за счёт средств казначейства Resupply — на данный момент уже возвращено более 643 тысяч reUSD. Оставшиеся украденные средства продолжают отслеживаться на блокчейне, команда заявляет, что ситуация находится под полным контролем.
Для разблокировки страхового пула и окончательного урегулирования последствий предстоит провести формальное голосование среди держателей токенов. Также в ближайшее время будут обновлены ключевые компоненты системы ResupplyPairCore.sol и ResupplyPairDeployer.sol, что должно навсегда устранить возможность подобной атаки.
Команда призывает всех участников сообщества следить за новостями и обновлениями через официальные форумы управления проектом.