Research
Nov 16, 2022
DFX Finance Attack Overview

Introduction

  • We take a look at the recent DFX Finance Attack, which lead to around $4M in losses.
  • We will analyze this incident step by step, showing how we approached it.
  • We will also go over the relevant best practices to avoid the issues that caused this attack.

We first go over some details about the attack that’s not related to the main vulnerability.

  • where the initial capital came from
  • what kind of transactions the attacker used to “set up” the attack
  • how the attacker moved the hacked funds.

Then, we will look at the main vulnerability.

  • If you want to check this only, you can skip to “The Main Attack Vector”.

Attack Analysis

To find the attack vector, let’s go through the exploit locally and see what actually happens.

The tools we used here are

The exploiter’s address is 0x14c19962E4A899F29B3dD9FF52eBFb5e4cb9A067.

The first transaction related to the address is this one.

Here, we see the account is funded by 0x8D0347eCb9344a6ce5BbaFA45eEceE68e53A008D.

Looking at that address’s internal transactions, we see the exploiter is funded via Tornado Cash.

Next, the attacker creates a contract 0x6cFa86a352339E766FF1cA119c8C40824f41F22D.

The attacker then calls the function App() onto this contract. We run this in Foundry and see this

Foundry Result.

OK, a bunch of approvals. Looking up the relevant addresses, we see that it’s just approving all the tokens to relevant DFX Finance pools. We can now make an educated guess that the attacker will go through all these pools and exploit them. Therefore, we can simply look at one or two exploit transactions to see what happened.

The next transaction is the big one, and we can suspect that this is the exploit tx. We see that the transaction targets the DFX-XIDR-USDC pool. To check, let’s see the token balances after the transaction was processed. Since we can see from etherscan that the relevant tokens are USDC and XIDR, let’s look at them.

Running this on block number 15941673 and 15941674, we see that the balances increased.

This is already at least $200K in profits, so this is an exploit transaction indeed.

Meanwhile, if we look at this exploit transaction, we see that UniswapV3 flash loans are used

We see that USDC and XIDR are flash loaned from Uniswap V3, so initial capital is required.

So before we go deeper inside how the attack actually works, we can consider the attacker’s strategy regards the need for initial capital. From the fact that the attacker flashloaned both USDC and XIDR from Uniswap V3 to attack the DFX’s USDC-XIDR pool, we can guess that the attacker requires both tokens to pull off the attack. Since the attacker now gained some capital via flashloan-assisted attack, the attacker does not need to use them anymore. Indeed, if the attacker needs some other token (for example, EUROC) the attacker simply swap some USDC. We can see that this is the case by noting that

  • the attacker does not use Uniswap V3 flash loans the first exploit transaction
  • the attacker, when dealing with a new pool, performs a swap at the beginning

For example, this transaction is the first exploit tx that deals with GYEN.

We see that the exploiter swaps some USDC for GYEN by looking at the call trace.

We also see some housekeeping done by the exploiter, after the very first exploit tx.

These five transactions

  • grab all 2271274940334125 of the stolen XIDR
  • first transaction is a test transfer, grabbing 1000
  • the second transaction transfers all the remaining stolen XIDR
  • approve the XIDR for swap on Uniswap V3 (third transaction)
  • swap some of the XIDR for 11.16 ETH on Uniswap V3 (fourth transaction)
  • send the remaining XIDR to the attack contract (fifth transaction)

so the attacker now doesn’t have to worry about gas costs anymore.

We also see that the attacker took out the stolen money, then either

  • swapped to ETH and sent to Tornado Cash (most assets)
  • remaining in the attack contract (TRYb)
  • remaining in the exploiter’s address (CADC)
  • bridged to Polygon (MATIC, 1 WETH, 820042 NZDS)
  • the attacker swapped 1 ETH to MATIC and bridged to Polygon

This fund retrieval part starts at block 15941949. Now let’s actually take a look at the attack.

The Main Attack Vector

As we mentioned before,

  • all exploit transactions are very similar and use the same vulnerability
  • the only differences are usage of Uniswap V3 flashloans / initial swap for tokens

Therefore, we take a look at the exploit transaction that doesn’t use Uniswap V3 flashloans or starts with a swap. That transaction would be the second tx for USDC-XIDR.

Looking at the call trace again and see the calls for the pool contract, we see that

  • there was a flashloan call to the pool contract
  • in the flashloan call back, the deposit function is called
  • after the flashloan, the withdraw function is called, sending assets to the exploiter contract

We can already get an idea on how this attack happened. One scenario is that the flashloan mechanism simply looks at its ERC20 balances to check if the contract that took the flashloan has returned its assets. In this case, the attacker can deposit the flashloaned assets to the pool. The pool contract will think that we have returned the assets as the ERC20 balances are back to normal, but in reality we deposited the assets, so we can withdraw them later as we want.

To check if this is the case, let’s take a look at the pool contract.

Indeed, we see that this is the case. There is no reentrancy protection for flash(), and the flashloan check is done simply using the ERC20 balances. We also see why the attacker required some initial capital - it’s because the attacker had to “pay” (deposit) the flash loan fee as well.

We note that this attack vector was in the pool contracts, which was not in the audit scope of our security audit of DFX Finance which was done on May 2022.

Our audit was for DFX Finance’s algorithmic stablecoin, which can be checked in this repository.

Preventing Such Attack Vectors

ReentrancyGuard

First, appropriately preventing reentrancy is always a good practice.

UniswapV2 pairs support flashloans, but the function is reentrancy protected.

If you want professional help at preventing such attacks, ask us for an audit.

About KALOS

KALOS is a flagship service of HAECHI LABS, the leader of the global blockchain industry. We bring together the best Web2 and Web3 experts. Security Researchers with expertise in cryptography, leaders of the global best hacker team, and blockchain/smart contract experts are responsible for securing your Web3 service.

We have secured over $60b worth of crypto assets across 400+ global crypto projects  — L1/L2 projects, defi protocols, P2E games, and bridges — notably 1inch, SushiSwap, Badger DAO, SuperRare, Klaytn and Chainsafe.

KALOS is the only blockchain technology company selected for the Samsung Electronics Startup Incubation Program in recognition of our expertise. We have also received technology grants from the Ethereum Foundation and Ethereum Community Fund.

Secure your smart contracts with KALOS.

Allen

Allen

Head of Security

About the author.

Allen is a researcher with a math background. He focuses on smart contract security and cryptography, while also studying zero knowledge proofs.