The Analysis of the Array Finance Security Incident

On July 18th, our DeFiRanger system ( reported a couple of suspicious transactions. After manual analysis, we confirm that these transactions are attacks to Array Finance. In the following, we will use an attack transaction to illustrate the attack process and the root cause of the vulnerability.

Attack Transaction

The attack transaction used in this blog is: 0xa17bbc7c9ab17aa88fdb5de83b41de982845e9c9c072efff6709dd29febf0daa

Attack Flow

Figure 1

As shown in Figure 1, we found that the attacker gained a profit of 186.62 WETH (we do not explicitly distinguish between WETH and ETH in this blog.) after borrowing the flash loan from AAVE.

Figure 2

The detailed attack process is shown in Figure 2.

From Figure 2, we can find the attacker gains profits in step 5 (Figure 2: Invoke the sell function). That's because the obtained 77.17 aBPT tokens are more valuable than the 49.9142 WETH deposited in step 3 (Figure 2: Invoke the buy function). In the following, we will analyze the code to understand why this attack can happen.

Code Vulnerability

The following code shows the sell function of Array Finance. In this function, Array Finance uses the balance of the ARRAY token owned by the attacker and invokes the internal _sell function to calculate the number of aBPT tokens that can be obtained by selling the ARRAY token.

The following is the implementation of the _sell function. It invokes the calculateLPtokensGivenArrayTokens to get the number of aBPT tokens that can be gained given a certain number of ARRAY tokens. Then this function burns ARRAY token and returns the aBPT token.

The following shows the implementation of the calculateLPtokensGivenArrayTokens function.

Note that, there are four arguments that can affect the calculation of amountLPToken. After reading the saleTargetAmount, we infer the formula is as following:

The arraySmartPool is the smart contract address of the Array Collater ( 0xa800cda5). The value of arraySmartPool.totalSupply() will increase when the attacker deposits fundings borrowed from the flash loan into the Array Collater (shown in the following table).

We can confirm this logic after reading the code of the arraySmartPool. The following shows the joinPool function of the arraySmartPool.

This function first invokes the SmartPoolManager. joinPool function to calculate the number of tokens (actualAmountsIn) that need to be obtained from the msg.sender. Then for each token, it invokes the _pullUnderlying function to deposit the token to arraySmartPool. At last, it invokes the _mintPoolShare and _pushPoolShare to mint aBPT token and transfer the minted aBPT token to msg.sender.

Note that the arraySmartPool inherits from the PCToken. The _mintPoolShare function invokes the _mint function, which is shown in the following.

The _mint function will increase the varTotalSupply variable, which is directly returned by the totalSupply(). Thus, this value is increased for each invocation of the joinPool.

Profit Estimation


In summary, the attacker exploits the vulnerability that the price mechanism of the Array Finance depends on the totalSupply of the aBPT token, which is manipulatable. The vulnerability has been discussed in our research paper DeFiRanger: Detecting Price Manipulation Attacks on DeFi Applications.

Junjie Fei, Yufeng Hu, Zilin Lin, Siwei Wu, Lei Wu, Yajin Zhou @BlockSec

(In alphabetical order by the last name)






The BlockSec Team focuses on the security of the blockchain ecosystem and the research of crypto hack monitoring and blocking, smart contract auditing.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store

The BlockSec Team focuses on the security of the blockchain ecosystem and the research of crypto hack monitoring and blocking, smart contract auditing.