DeFi Security Lecture 2 — Flash Loan Attacks

Beaver Finance
beaver-smartcontract-security
14 min readNov 21, 2021

--

If you’ve been into DeFi for a minute, you’ve likely heard about flash loans before. However, you might not exactly know the utility of flash loans, why/what makes them different from normal decentralized lending borrowing, or why do you so often hear about attacks on flash loans? And most important of all, if you’re thinking about taking out a flash loan, how do you protect your assets from an impending attack?

The sensei beaver is back once again to help the baby beavers navigate the world of DeFi safely. Let’s get started!

Term Explanation

Flash Loan: Simply put, flash loan is a decentralized unsecured loan that can be taken out without the involvement of an intermediary. Typical lending protocols are built on (over)collateral mechanisms to make sure the borrower repays the principal with interest. However, a borrower is not required to provide any collateral to take out a flash loan.

How do Flash Loans work?

Flash loans take place in one block without any collateral. After taking out the loan, the user achieves the purpose of flash loan and repays it with the accrued interest. This whole process takes place in one block.

If you borrow some assets in block 2000, you need to repay the loan with interest in the same block. You cannot repay it in block 2001. If the smart contract providing the flash loan doesn’t receive the repayment in the same block, it would abort the transaction. That’s a flash loan, which means a quick loan that is short-lived.

Flash Loan Attack:

Based on the mechanism of flash loans, malicious parties find it easy to take out large flash loans, and then use these funds to manipulate the market or employ various DeFi protocols to obtain considerable profits, usually at the expense of ordinary investors and platform users.

Pump and Arbitrage

The idea is to pump the bag using a flash loan and then execute the arbitrage opportunity.

Let’s see an example:

A user borrows a large amount of ETH from a lending protocol using a flash loan feature. Say they take a 10,000 ETH flash loan. Then they deposit 5,000 ETH to a lending protocol as collateral to get a typical decentralized loan. This is a normal loan, not a flash loan. With that amount of money, the user gets 100 ABC tokens. The price of 1 ABC token is 50 ETH.

User A then employs margin trade to short ETH in favor of the ABC token. They deposit 1000 ETH and execute margin trading receiving 5000 ETH, 5 times the leverage. Then 5000 ETH is swapped with ABC tokens on a decentralized exchange. Because of low liquidity, the price of the ABC token on that decentralized exchange skyrockets. The price of 1 token ABC becomes 100 ETH now (2x from the previous price, 50 ETH).

Remember that the user still has 100 ABC tokens from their previous loan. The user then dumps all the ABC tokens on another decentralized exchange. They receive 10,000 ETH. They repay the flash loan, keeping 4000 ETH as profit. While the user lets the position in the margin trading protocol go default.

Oracle Manipulation

User B has 200 ABC tokens and wants to borrow 5,000 ETH with 200 ABC tokens as collateral on a decentralized lending protocol. In the lending protocol, the price of 1 ABC is 50 ETH. So User B’s collateral is 2x of the loan. The price of 100 ABC is 5000 ETH, and the rest of ABC (another 100 ABC) becomes pure collateral.

But how does the lending protocol decide the price of 1 ABC is 50 ETH? It checks the price of this pair, ABC/ETH, on a decentralized exchange.

And how does a decentralized exchange decide the price of the pair, ABC/ETH? It has a certain algorithm to calculate the price. It derives the price of the pair from the liquidity of the pair. For example, there is 100 ABC and 5,000 ETH. So the price is 50 ETH for 1 ABC.

Imagine user B takes out a flash loan of 3,000 ETH from a lending protocol. With this amount of ETH, they buy 60 ABC from the decentralized exchange. So the liquidity in the decentralized exchange for the pair, ABC/ETH, becomes 40 ABC for 5,000 ETH, and the price of 1 ABC becomes 125 ETH.

Now, they borrow ETH again from a lending protocol. This time with 200 ABC and 2x leverage, they can get 12,500 ETH. Notice the difference. By using flash loans, user B was able to manipulate the oracle price into getting a cheaper price for ETH.

Reentrancy Attack

A reentrancy attack is a callback method of the attacker’s contract being called and called again before the accounting has been settled. We have discussed it in great detail in Lecture 1 of the Beaver Security Series.

Flash loan logic can also be hidden in the reentrancy code:

For example, your smart contract accepts stable coins, and if people send some stable coins to your smart contract, your smart contract will mint your own token for the user.

But in this process, your smart contract calls an external method called safe transfer from, a standard method for approval in ERC-20 token smart contract.

However, you forgot to check the smart contract’s address belonging to the approved stable coin smart contracts. So you call safe transfer from on the attacker’s smart contract. However, the user being a malicious party, their smart contract mints your own token without your knowing and inflates the value of your token. The role of the flash loan is to amplify the damage.

Protocols Supporting Flash Loans

There are several DeFi lending/borrowing protocols supporting flash loans. To get a flash loan from any protocol, a user needs to create a smart contract. You cannot get a flash loan using your own account. The protocol will feed the loan to this smart contract. You do what you want to do with the borrowed money within this smart contract.

Aave

Aave is a lending protocol where users can borrow and lend assets, and it is also the first DeFi protocol to offer flash loans. To get a flash loan on Aave, you need to execute the flash loan method of the lending pool smart contract. In this method, you give your smart contract’s address, the address of the principal reserve, the amount you want to borrow, and some parameter string that will be passed to your smart contract. Your smart contract must follow some rules to receive the flash loan.

This method sends the fund to your smart contract after ensuring it has enough funds in the pool. The method executes the action on your smart contract. Then it checks whether the returned fund with a small fee has been returned or not. If the answer is yes, the method updates the state of the reserves. If things go awry, the method reverts the transaction.

Uniswap

Uniswap is an automatic market maker or a decentralized exchange. Uniswap offers flash loans. But the term is different. It’s called flash swap. The method is swap

.

You withdraw any token on Uniswap to your smart contract. You do whatever you want with them. Then you have two options. The first option is you return them with a fee. The second option is you pay Uniswap with the corresponding pair tokens. When you trade tokens in Uniswap, you basically call the same method.

For example, you want to buy DAI with your ETH. The process runs like this. Uniswap gives you DAI first. Then you do nothing with the DAI you got. Finally, you give your ETH to Uniswap as payment for the DAI you got. So normal trading is just a flash loan but you do nothing with the borrowed asset. You just pay them with another token.

DyDx

DyDx is a decentralized exchange that supports other features, like margin trading, among other things. They don’t support flash loans natively, but they have a SoloMargin smart contract. In this smart contract, you can execute many operations. So to execute a flash loan, you just need to execute a withdrawal action, a call function, and a deposit action in one transaction.

The withdrawal action is to borrow a loan. The call function is what you want to do with this borrowed fund. The deposit action is to return the loan.

Real-World Example of a flash loan attack on Cream Finance

C.R.E.A.M. Finance is a blockchain agnostic, decentralized peer-to-peer lending platform based on a fork of Compound Finance.

C.R.E.A.M. bridges liquidity across underserved assets by providing algorithmic money markets to these underserved assets. Users can supply any supported assets and use these supplied assets as collateral to borrow any other supported assets. C.R.E.A.M. has launched on Ethereum and Binance Smart Chain.

On October 27, 2021, Cream Finance, one DeFi rising lending protocol, was attacked, resulting in a loss of approximately USD 130 million. The stolen funds were mainly Cream LP tokens and other ERC-20 tokens. It is reported that this is the third-largest DeFi hacking in history (although the two larger hacking incidents have funds returned). In addition, Cream Finance had suffered multiple lightning loan attacks before and lost 37.5 million US dollars in February. Another $18.8 million was lost.

Case Analysis

Review of the First Attack:

Attack process:

  1. The attacker borrowed 500 ETH from Uniswap Lightning Loan;
  2. Staked 500 ETH into the crETH contract to obtain crETH certificate; crETH smart contract address:
  3. Loan 19,480,000 AMP from crAMP contract;
  • When lending, the cToken contract will first transfer AMP tokens to the attacker through the doTransferOut function and then record the attacker’s loan amount to accountBorrows;
  • But the transfer function of AMP tokens will call back the tokensReceived function of the attacker contract through the hook (_callPostTransferHooks) function;
  • The attacker contract called the crETH contract again in the tokensReceived function, lending 355 ETH;
  • Since the first loan contract is the crAMP contract, and the second reentry call is the crETH contract, the anti-reentrant modifier (nonReentrant) of the borrow function does not work;
  • And the borrow function is a borrowing record (accountBorrows) that is modified after transferring money to the user, causing the attacker to make excess borrowing;

4. Then the attacker uses another contract (0x0ec3) to liquidate the contract (0x38c4) that has been liquidated so that the transaction will not fail due to excessive borrowing;

5. Later, the attack contract (0x38c4) transferred the crETH certificate to the 0x0ec3 contract, and the 0x0ec3 contract used these certificates to redeem about 187.58 ETH;

6. In the end, the attacker obtained about 542.58 (187.58 + 355) ETH and 9,740,000 AMP tokens in this transaction;

7. Eventually, the attacker returned the flash loan and left with a profit. Other attack transactions are similar.

Review of the Second Attack:

Attack Process:

  1. The attacker borrowed 500 million DAI from DssFlash in a flash loan and then mortgaged the 500 million DAI loaned to the yearn yDAI pool to obtain about 450 million yDAI certificates.

2. The attacker then adds the obtained yDAI tokens to Curve’s yDAI/yUSDC/yUSDT/yTUSD pool for single-currency liquidity addition to obtain corresponding liquidity certificates. Then the attacker mortgaged the obtained vouchers to the yUSD pool to obtain yUSD vouchers in preparation for subsequent mortgages in the Cream crYUSD loan pool.

3. After that, the attacker began to mortgage Cream’s crYUSD loan pool to obtain yUSD certificates. In order to expand its mortgage scale, the attacker loaned about 524,000 WETH from AAVE Lightning Loan and mortgaged it to Cream’s crETH pool.

4. The attacker mortgaged a large amount of ETH in the crETH pool to make it have enough borrowing capacity to lend all the yUSD in the crYUSD pool and re-pledged it to the crYUSD pool, and then expand in the form of leverage by revolving loans in the crYUSD pool The yUSD collateralized scale in the crYUSD pool is used to prepare for subsequent price manipulation and profitability.

5. Then, in order to obtain yDAI/yUSDC/yUSDT/yTUSD 4Pool vouchers to manipulate the price, the attacker used about 1,873 ETH to exchange about 7.45 million USDC from Uniswap V3, and used Curve 3Pool to convert it into about 3.38 million DUSD tokens.

6. Next, the attacker uses the obtained DUSD tokens to redeem it from YVaultPeak yDAI/yUSDC/yUSDT/yTUSD 4Pool voucher, and use this voucher to retrieve yDAI/yUSDC/yUSDT/yTUSD tokens from the yUSD pool.

7. Then the attacker began to carry out the key operations of the attack. It transferred approximately 8.43 million yDAI/yUSDC/yUSDT/yTUSD tokens directly back to the yUSD pool. Since they were not mortgaged through normal mortgage operations, these 8.43 million The yDAI/yUSDC/yUSDT/yTUSD tokens are not separately accounted for, but are directly distributed to the holders of the yDAI/yUSDC/yUSDT/yTUSD voucher, which is equivalent to directly raising the price of their shares.

8. In crToken, because the price of its collateral was maliciously increased, the attacker’s mortgage of a large amount of yUSD could make it lend more funds, and finally, the attacker lent all the other 15 pools of Cream.

9. In the end, the attacker returned the flash loan and left the market after borrowing other pools.

Contract Analysis

We check the specific borrowing logic in Cream’s crToken lending pool. From the cToken contract, we can see that the main loan check is in the borrowAllowed function:

We follow up the borrowAllowed function and we can see that in line40, it will be based on The getHypotheticalAccountLiquidityInternal function checks the sum of the asset value of all cTokens and the sum of the loaned asset value corresponding to the account in the real-time state, and compares the value of the cToken’s asset value with the sum of the loaned Token value to determine whether the user can continue to borrow.

We follow up the getHypotheticalAccountLiquidityInternal function, and we can find that the value of the collateral is obtained from line 54 oracle.getUnderlyingPrice.

We follow up the getUnderlyingPrice function of the oracle, and we can easily find that it will get the price through the getYvTokenPrice function of 26 lines of the token.

Continue to follow up on the getYvTokenPrice function. Since yvTokenInfo.version is V2, the price will be obtained through the pricePerShare function of yVault.

Following up on pricePerShare, we can find that it directly returns _shareValue as the price, and _shareValue calculates the price of a single share by dividing _totalAssets by the total number of shares in the contract (self.totalSupply). Therefore, the attacker only needs to manipulate _totalAssets to raise it to increase the price of a single share so that the value of the attacker’s collateral becomes higher to lend more other tokens.

We can check how _totalAssets is obtained. From line 772, we can clearly see that _totalAssets is the number of yDAI/yUSDC/yUSDT/yTUSD tokens directly taken from the current contract, and the amount of assets staked in the strategy pool Added together. Therefore, by directly transferring yDAI/yUSDC/yUSDT/yTUSD tokens to the yUSD contract, the attacker can increase the share price and complete profit.

Through Ethtx.info, you can clearly see the changes before and after pricePerShare:

Defensive Measures — How to protect your assets from flash loan attacks?

Flash loan is still a nascent concept in DeFi, and so the protocols built on top of this tech stack are yet to become robust and fully immune to all these tricks and manipulations. But yes one can take some preventive measures to prevent such malicious action from harming their interests and assets. Let’s explore the same.

Using Decentralized Pricing Oracles Like Chainlink & Band Protocol:

One optimal way DeFi can mitigate this flash loan attack is by making use of decentralized pricing oracles like Chainklink and Band Protocol to fetch price feeds instead of relying on a singular DEX platform (which is vulnerable to attacks)

For instance, after a flash loan attack incident, Alpha Homora decided to launch their Alpha Oracle Aggregator in May 2021.

Using Tools Which Can Identify Flash Loan Attack Possibility:

Flash loan attackers make use of the delay which is caused by the DeFi platform to honor the transactions, what is any tool that can help you prevent this loop exploitation, yes there are some tools like OpenZeppelin.

OpenZeppelin Contracts helps you minimize risk by using battle-tested libraries of smart contracts for Ethereum and other blockchains. It includes the most used implementations of ERC standards.

DeFi platforms can leverage such kinds of tools to detect smart contract bugs & exploits and also trace any unusual activity so that a proactive defense mechanism can be taken to neutralize attacks.

Openzepplin is already being employed by Synthetix, Yearn Finance, and Opyn among other projects to single out such attacks.

“Many more tools similar to OpenZeppelin are being developed and will be needed and as more attacks get identified more secure this Defi platform will become with time passing by. Till then as a user exercise your trade with that extra bit of caution of in-depth research about the platform you have decided to use.”

Summing up

The very first flash loan attack was caused by the incompatibility between the Cream lending model and AMP tokens. Since the AMP token transfer will use the hook function to call back the target address, and the Cream cToken contract will only record the loan amount after the loan transfer, which eventually causes the problem of excess borrowing.

The second attack was the use of lightning loans for price manipulation. Because Cream’s lending pool directly used its pricePerShare interface when obtaining the yUSD pool share price, this interface was added to the collateral balance of the contract and the amount of collateralized assets in the strategy pool. Divide the total number of shares to calculate the price of a single share. Therefore, the user can easily increase the price of a single share by directly transferring the collateral to yUSD, and finally allows the collateral in the Cream loan pool to lend more funds.

Beaver Finance team up experienced security experts on building our system and would continuously share our findings on DeFi security topics.

Stay Alert, Stay Safe!

Reference:

1, Introduction to Flash Loans: What is a Flash Loan Attack?https://blog.coincodecap.com/flash-loan

2, Cream Finance Attacked Recap

https://hacked.slowmist.io/en/

3,https://docs.cream.finance/developer/crtokens

--

--

Beaver Finance
beaver-smartcontract-security

Beaver Finance is a Single-Asset Intelligent Yield Enhancing platform with the Option-based cutting-edge hedging solution for Impermanent Loss.