18 июля наша система DeFiRanger сообщила о нескольких подозрительных транзакциях. После ручного анализа мы подтвердили, что эти транзакции являются атаками на Array Finance. Далее мы будем использовать одну атакующую транзакцию, чтобы проиллюстрировать процесс атаки и первопричину уязвимости.
Атакующая транзакция
Атакующая транзакция, используемая в этом блоге: 0xa17bbc7c9ab17aa88fdb5de83b41de982845e9c9c072efff6709dd29febf0daa
Ход атаки

Как показано на Рисунке 1, мы обнаружили, что атакующий получил прибыль в размере 186,62 WETH (в этом блоге мы не будем явно различать WETH и ETH) после получения флэш-займа от AAVE.

Подробный процесс атаки показан на Рисунке 2.
- Сначала атакующий вызвал функцию
buyконтракта Array Finance. Атакующий получил 430 токенов ARRAY, выпущенных Array Finance, используя 45,91 WETH. - Затем атакующий пять раз вызвал функцию
joinPoolконтракта с закрытым исходным кодом (Array Collater - 0xa800cda5). Он/она внёс 676 410,58 DAI + 679 080,46 USDC + 901,82 WETH + 20 WBTC + 20 renBTC и получил 726,38 токенов aBPT, выпущенных Array Collater. - Атакующий вызвал функцию
sell, чтобы сжечь 430 токенов ARRAY, и получил 77,17 токенов aBPT. - Наконец, атакующий вызвал функцию
exitPoolконтракта Array Collater. Он/она сжёг 804,55 токенов aBPT, полученных на предыдущих двух шагах, и получил 748 271,55 DAI + 751 225,08 USDC + 997,62 WETH + 22,63 WBTC + 22,74 renBTC.
Из Рисунка 2 видно, что атакующий получает прибыль на шаге 5 (Рисунок 2: Вызов функции sell). Это происходит потому, что полученные 77,17 токенов aBPT более ценны, чем 49,9142 WETH, депонированных на шаге 3 (Рисунок 2: Вызов функции buy). Далее мы проанализируем код, чтобы понять, почему возможна эта атака.
Уязвимость в коде
Следующий код показывает функцию sell контракта Array Finance. В этой функции Array Finance использует баланс токена ARRAY, принадлежащего атакующему, и вызывает внутреннюю функцию _sell для расчёта количества токенов aBPT, которые можно получить, продав токен ARRAY.

Далее представлена реализация функции _sell. Она вызывает функцию calculateLPtokensGivenArrayTokens, чтобы получить количество токенов aBPT, которые можно получить за определённое количество токенов ARRAY. Затем эта функция сжигает токен ARRAY и возвращает токен aBPT.

Далее показана реализация функции calculateLPtokensGivenArrayTokens.

Обратите внимание, что есть четыре аргумента, которые могут влиять на расчёт amountLPToken. После изучения saleTargetAmount мы предполагаем, что формула следующая:
arraySmartPool.totalSupply() * (1 - (1 - amount / ARRAY.totalSupply()) ^ (1000000 / reseveRatio))
arraySmartPool — это адрес смарт-контракта Array Collater (0xa800cda5f3416a6fb64ef93d84d6298a685d190d). Значение arraySmartPool.totalSupply() увеличивается, когда атакующий вносит средства, заимствованные с помощью флэш-займа, в Array Collater (показано в следующей таблице).
TxnIndex: 64 arraySmartPool.totalSupply(): 110162296218708026400
TxnIndex: 107 arraySmartPool.totalSupply(): 165243444328062039600
TxnIndex: 150 arraySmartPool.totalSupply(): 247865166492093059400
TxnIndex: 193 arraySmartPool.totalSupply(): 371797749738139589100
TxnIndex: 236 arraySmartPool.totalSupply(): 557696624607209383650
TxnIndex: 280 arraySmartPool.totalSupply(): 836544936910814075475
Мы можем подтвердить эту логику после изучения кода arraySmartPool. Ниже показана функция joinPool контракта arraySmartPool.

Эта функция сначала вызывает функцию SmartPoolManager.joinPool для расчёта количества токенов (actualAmountsIn), которые нужно получить от msg.sender. Затем для каждого токена она вызывает функцию _pullUnderlying, чтобы депонировать токен в arraySmartPool. Наконец, она вызывает _mintPoolShare и _pushPoolShare для выпуска токена aBPT и передачи выпущенного токена aBPT msg.sender.
Обратите внимание, что arraySmartPool наследуется от PCToken. Функция _mintPoolShare вызывает функцию _mint, которая показана ниже.
Функция _mint увеличивает переменную varTotalSupply, которая напрямую возвращается функцией totalSupply(). Таким образом, это значение увеличивается при каждом вызове joinPool.
Оценка прибыли
| Адрес атакующего | Атакующая транзакция | Прибыль (ETH) |
|---|---|---|
| 0x1337 | 0xa17bbc7c9ab17aa88fdb5de83b41de982845e9c9c072efff6709dd29febf0daa | 186.62073907323577 |
| 0x1b4fb735b51a25b280499710d02f50e4f772949664f9eb088e9d968b41ca2a1c | 59.338842936817095 | |
| 0x356ae8a278754551d9d2ae7dc0ea876b37c342ff2d010bee14aa253bb0b6030b | 18.827787420260467 | |
| 0x388fd59eab65b6034c96c01a21197eb2889d6507f84ff07e553749c541563962 | 5.880854505948256 | |
| 0xf4227ca3c8e8b5c8a0b10f034c6dee6556788c618e4cd289dc343b3247e85add | 0.4327422187881 | |
| Всего | 271.1009661550497 | |
| 0x80d2 | 0xf061f8fc19c894ec37310ff59977ec97de55fd1494f1b1e66ae89188552d5c60 | 1.8414029470248867 |
| Всего | 1.8414029470248867 | |
| Всего | 272.9423691020746 |
Резюме
В итоге, атакующий использует уязвимость, заключающуюся в том, что ценовой механизм Array Finance зависит от totalSupply токена aBPT, который можно манипулировать. Эта уязвимость обсуждается в нашей исследовательской статье DeFiRanger: Detecting Price Manipulation Attacks on DeFi Applications.
Благодарности
Junjie Fei, Yufeng Hu, Ziling Lin, Siwei Wu, Lei Wu, Yajin Zhou @BlockSec
(В алфавитном порядке по фамилии)
О компании BlockSec
BlockSec — новаторская компания в сфере блокчейн-безопасности, основанная в 2021 году группой всемирно известных экспертов по безопасности. Компания стремится повышать безопасность и удобство использования для развивающегося мира Web3, чтобы способствовать его массовому внедрению. Для этого BlockSec предоставляет услуги по аудиту безопасности смарт-контрактов и EVM-цепочек, платформу Phalcon для разработки в области безопасности и проактивного блокирования угроз, платформу MetaSleuth для отслеживания и расследования движения средств, а также расширение MetaDock для разработчиков web3, позволяющее эффективно работать в криптомире.
На сегодняшний день компания обслужила более 300 уважаемых клиентов, таких как MetaMask, Uniswap Foundation, Compound, Forta и PancakeSwap, и привлекла десятки миллионов долларов США в рамках двух раундов финансирования от ведущих инвесторов, включая Matrix Partners, Vitalbridge Capital и Fenbushi Capital.
Официальный сайт: https://blocksec.com/
Официальный аккаунт в Twitter: https://twitter.com/BlockSecTeam



