Как ошибка учёта позволила вывести 9,25 ETH из Reddio Vault

Введение
Reddio Vault - это хранилище в сети Ethereum, куда пользователи вкладывают криптовалюту и получают взамен токены доли. Эти токены подтверждают право владельца на часть активов, лежащих в хранилище.
stETH - это «обёрнутый» эфириум от сервиса Lido. Когда пользователь вкладывает ETH в Lido, он получает stETH. Этот токен растёт в стоимости, отражая начисление наград за поддержание сети Ethereum.
Flash-loan - это мгновенный кредит, который берётся и возвращается в рамках одной транзакции. Если в конце транзакции кредит не возвращён - вся операция отменяется.
Ход инцидента
1. Злоумышленник взял мгновенный кредит на 1,139 WETH из протокола Balancer. Эти средства нужны были для начала атаки.
2. Он развернул собственный вспомогательный контракт и через открытую для всех функцию
registerErc20() зарегистрировал stETH как новый актив под названием rsvstETH. Функция была permissionless - это значит, что любой пользователь мог зарегистрировать актив без разрешения администраторов.3. Злоумышленник внёс 1,130 ETH в основное хранилище (ETH-vault) и получил почти все выпущенные доли rsvETH - токены, подтверждающие право на часть активов этого хранилища.
4. Затем он дополнительно внёс 9,34 stETH. Из-за ошибки в учёте этот депозит увеличил общий баланс stETH, который система использовала при расчёте стоимости активов ETH-vault. По сути, один и тот же баланс stETH начал одновременно обеспечивать две разные доли: rsvETH и rsvstETH.
5. Это искусственно завысило цену долей rsvETH. Злоумышленник вывел свои rsvETH по этой завышенной цене и получил около 1 139,5 ETH.
6. После этого он погасил rsvstETH обратно в stETH, обменял полученные stETH на ETH через Curve - децентрализованную биржу - и вернул мгновенный кредит в Balancer.
7. После погашения займа и завершения всех операций на адресе злоумышленника осталось около 9,25 ETH. Это чистый ущерб для протокола.
Почему это стало возможным
Функция
getTotalAssetBalance(ETH) для позиции Lido возвращала сырой баланс stETH, находящийся на контракте хранилища. Когда злоумышленник зарегистрировал тот же stETH как новый актив rsvstETH, система не поняла, что это один и тот же баланс. Один депозит stETH начал одновременно обеспечивать две разные доли.Когда злоумышленник вносил stETH, общий баланс рос, и цена rsvETH росла вместе с ним. Но реальное обеспечение не удвоилось - оно осталось прежним. Это позволило вывести гораздо больше, чем было вложено.
Ограничение на вывод в 2 % от общей стоимости не помешало манипуляции, потому что злоумышленник контролировал почти все доли rsvETH и мог выводить постепенно в рамках одной транзакции.
Детали расследования: движение средств
Вся атака прошла в рамках одной транзакции. Злоумышленник использовал адрес:
Средства не покидали этот адрес в виде окончательного вывода - операции были замкнуты внутри одной транзакции. Чистый результат атаки - около 9,25 ETH - остался на балансе этого же адреса.
Заключение
Инцидент в Reddio Vault показал, что открытая регистрация активов без проверки на дублирование может привести к двойному учёту. Один и тот же баланс stETH был использован для обеспечения двух разных долей, что искусственно раздуло цену и позволило вывести средства. Отсутствие проверки на уникальность актива при регистрации и неправильный расчёт общего баланса стали ключевыми факторами.


