Back to Blog

Анализ инцидента безопасности в Array Finance

Code Auditing
July 19, 2021
3 min read

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

Транзакция атаки

Транзакция атаки, используемая в этой статье: 0xa17bbc7c9ab17aa88fdb5de83b41de982845e9c9c072efff6709dd29febf0daa

Ход атаки

Рисунок 1
Рисунок 1

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

Рисунок 2
Рисунок 2

Подробный процесс атаки показан на Рисунке 2.

  • Сначала злоумышленник вызвал функцию buy в Array Finance. Он получил 430 токенов ARRAY, выпущенных (minted) 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():  5576

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit