Как логические ошибки в смарт-контрактах привели к сериям атак в DeFi
11.03.2026 | CoinKyt Company

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


За несколько дней произошло три отдельных инцидента:


- кража ликвидности из пула MT/WBNB в сети BNB Smart Chain

- эксплуатация уязвимости в контракте PurchaseBundler протокола GONDI

- ошибка контроля доступа в контракте MoltEVM в сети Base


Расследование КоинКит разбирает механику атак и движение похищенных средств.




Кража 381.7 WBNB из пула MT/WBNB


В одной транзакции злоумышленник смог извлечь из пула ликвидности 381.7 WBNB чистой прибыли.


Для атаки использовался flash-loan.


Flash-loan — это мгновенный займ внутри одной транзакции. Его можно взять без залога, но он должен быть полностью возвращён до завершения той же транзакции.

 


Ход инцидента


Атака была проведена в несколько шагов.


1️⃣ Сначала злоумышленник взял крупный flash-loan в WBNB. WBNB — это «обёрнутый» токен BNB, который используется в DeFi-контрактах.


2️⃣ Далее он начал взаимодействовать с пулом ликвидности MT/WBNB. В процессе операции из пула было сожжено 6,735,516 MT


3️⃣ После изменения баланса токенов атакующий совершил обмен и получил 1,198 WBNB.


4️⃣ В конце транзакции flash-loan был возвращен, а разница составила 381.7 WBNB



Почему это стало возможным


Причина атаки связана с особенностями логики sell-burn в токене MT.


Во время продажи токены MT не просто отправляются в пул ликвидности. Контракт дополнительно записывает тот же объём проданных токенов в переменную pendingBurnAmount.


Фактически происходит следующее:


1. Токены продаются и попадают в пул ликвидности.


2. Тот же объём помечается как будущий burn.


Позже функция extractFromPoolForLpMining() вызывает внутреннюю функцию _executePendingBurn().


Эта функция:


- напрямую уменьшает баланс MT у pair-контракта;

- отправляет токены на dead-адрес;

- вызывает sync().


В результате резерв MT в пуле уменьшается принудительно, а резерв WBNB при этом остаётся прежним.


Пул становится перекошенным: MT резко уменьшается, а WBNB остаётся на прежнем уровне.


Атакующий использовал этот момент и продал MT в уже искажённый пул, получив значительно больше WBNB, чем позволяла реальная ликвидность.



Детали расследования: движение средств


После атаки средства были переведены на адрес: 0xDB0901A3254f47c0CE57fFFCE2C730Bc33A1c0e1


Дальнейшая цепочка операций:

 
1️⃣ WBNB → обмен на USDC

2️⃣ перевод через мост Stargate в сеть Ethereum

3️⃣ обмен USDC → DAI

4️⃣ отправка средств в приватный протокол Railgun


Railgun — это протокол приватности, который скрывает происхождение средств в блокчейне.

 



Инцидент GONDI (~$230k)


Ход инцидента


9 марта 2026 года был зафиксирован инцидент в NFT-кредитном протоколе GONDI.


Атакующий использовал уязвимость в контракте PurchaseBundler — вспомогательном контракте, который объединяет несколько операций с NFT в одну транзакцию.


В результате атаки злоумышленник смог получить 39 NFT, не погасив связанный с ними займ.


Общий ущерб оценивается примерно в $230 000.

 

Как была проведена атака


Злоумышленник развернул собственный helper-контракт (вспомогательный смарт-контракт) и через него начал отправлять вызовы функции:


PurchaseBundler.executeSell()


Контракт ожидал, что внутри операции будет выполнено погашение займа (repayLoan).


Но атакующий передал специально подготовленные данные вызова, которые выглядели корректными для проверки контракта.


После этого происходила следующая последовательность:


1️⃣ контракт обрабатывал команду продажи


2️⃣ логика доходила до этапа SellAndRepayExecuted


3️⃣ контракт переводил NFT атакующему


При этом реального погашения займа не происходило.

 

Почему это стало возможным


Проблема находилась в механике проверки входных данных.


Контракт проверял не всю структуру вызова, а только часть параметров после первых 4 байт calldata.


Calldata — это входные данные транзакции, которые определяют, какая функция контракта вызывается и с какими параметрами.


Из-за такой неполной проверки злоумышленник смог сформировать входные данные, которые:


- выглядели корректными для проверки

- но фактически запускали другую логику

Далее контракт использовал функцию multicall.


Multicall — это механизм, который позволяет выполнить несколько вызовов функций в одной транзакции.


С помощью multicall атакующий подменил вызов функции repayLoan другой операцией.


Контракт продолжал выполнение и доходил до этапа передачи NFT, хотя займ не был погашен.

 

Детали расследования: движение средств


После получения NFT злоумышленник начал постепенно распродавать активы.


По данным расследования:


- часть NFT уже продана на рынке

- часть конвертирована в ETH / WETH

WETH (Wrapped ETH) — это версия ETH, адаптированная для работы в смарт-контрактах.


На момент расследования не все похищенные NFT были реализованы.




Инцидент MoltEVM (~$125k)


Что произошло


6 марта 2026 года произошёл инцидент в сети Base, связанный с контрактом MoltEVM.


Контракт содержал функцию: mintFromSpawner()


Она предназначалась для выпуска новых токенов через доверенные контракты-эмитенты.


Однако из-за ошибки в проверке доступа злоумышленники смогли обойти защиту и выпускать токены самостоятельно.


После выпуска токены сразу продавались в публичный пул ликвидности.


Общий ущерб составил около $125 000.

 

Как работала атака


Атакующие разворачивали собственные минимальные helper-контракты.


Эти контракты имитировали поведение доверенных эмитентов.


Через них злоумышленники вызывали функцию: mintFromSpawner()


Контракт выпускал новые токены, которые атакующие сразу продавали в пул ликвидности: 0x064c9fbed2cce0fdc3600777492bc0413b2cf95e


Продажа происходила в обмен на ETH или WETH.


Таким образом злоумышленники конвертировали вновь выпущенные токены в реальные активы.

 

Почему это стало возможным


Проблема находилась в механизме контроля доступа. Контракт использовал модификатор: onlySpawnerToken


Он должен был разрешать выпуск токенов только доверенным контрактам. Однако фактически проверка состояла всего из двух условий:


1️⃣ вызывающий адрес является контрактом


2️⃣ функция initialized() возвращает true


Это означало, что любой контракт, реализующий функцию initialized() → true мог пройти проверку.


Злоумышленники просто разворачивали фальшивые helper-контракты с такой функцией и получали доступ к mintFromSpawner().


После этого они могли выпускать произвольные объёмы токенов.

 

Движение средств


Расследование показало участие как минимум двух адресов.


Первый атакующий


Адрес: 0x5e4C45725b1A7c9D42e903e06AEE90271842bFE4


Часть средств (~$30k) была выведена через мост Relay.link.


Bridge — это протокол, который позволяет переводить активы между блокчейн-сетями.


Средства были переведены из сети Base в Ethereum.


После этого они были отправлены на биржу BitGet.


Основная часть средств остаётся на адресе атакующего в сети Base.

 

Второй атакующий


Второй адрес не выводил средства. Все активы остаются на балансе в сети Base.



Визуализация движения средств:
https://explorer.coinkyt.com/ru/snapshot/bdfd0bbd-5d05-41e5-83b2-e6072526200d




Заключение


Рассмотренные инциденты демонстрируют разные типы уязвимостей, которые продолжают появляться в DeFi-протоколах.


Атака на пул MT/WBNB была связана с логической ошибкой в механике burn, позволившей искусственно изменить баланс резервов. Инцидент GONDI показал риски неполной проверки данных при сложных мультивызовах контрактов. Ошибка в MoltEVM стала примером неправильной реализации контроля доступа.

 


Команда КоинКит продолжает мониторинг связанных адресов и анализ дальнейшего движения активов.