bZX was 'hacked' recently, and it's quite interesting as a milestone for decentralized finance. Featuring a $1M flash loan, price manipulation, and on-chain price oracles (Kyber). All on the week after "$1 billion dollars in decentralized finance". Let's dig in!

Overview

  • What is bZX and margin lending
  • How does the price oracle work
  • Why is it bad to use Uniswap/on-chain feeds for this
  • How did flash loans make this happen?

What is bZX and margin lending

bZX is a protocol for margin trading, a branch of trading. In normal trading, you try to make a profit/loss from the fluctuations in the price of an asset. Because this is DeFi, those assets are tokens.

If the token goes up in value, you might sell. If it goes down to 0, you've lost your money. A trader tries to predict the market.

Margin trading is the same concept, with a multiplier. You might think ETH will go up (long position), but not have enough capital to invest. So you take out a leveraged position - where you invest 10 ETH with 10x leverage, and get an effective balance of 100 ETH. If the price goes up, you can close the position and make 10x what you normally would've without the leverage. However if the price goes down, your position becomes at risk of liquidation, since the collateral you've put down is worth less than the 10% of the original 100 ETH.

Margin trading requires that you have the asset you want to leverage, whereas margin lending means it's just borrowed for whatever you have. It's as simple as that.

A nice visual taken from bZX's Fulcrum trade dApp.

The need for price oracles

For these protocols to work, we need information about the price of the assets, so we can decide the value of the positions. This is commonly called a "price oracle", because when we first started doing this on the blockchain, getting external data felt like dark magic. Nowadays at tBTC, we call it a "price feed".

Price oracles are used everywhere in decentralized finance. The DAI stablecoin is stable precisely because we can determine how much ether "is in" a US dollar, and establish a cryptoeconomic system of checks and balances around that. Set Protocol, which tokenises a portfolio (eg. 50% ETH, 50% BTC), uses a price feed to determine when portfolios need rebalancing.

In both of Maker and TokenSets, their oracles are off-chain. Meaning, the price data is taken from an external set of sources like centralized exchanges (Coinbase, Binance, etc.), and medianized and whatnot into an on-chain value.

bZX relying on Uniswap

In contrast, bZX protocol relied on some on-chain price sources, through the Kyber Network of reserves.

A brief explainer: Uniswap is an automatic market maker (AMM), meaning trades are instant. When someone wants to trade a token for another, the price is determined automatically, and the tokens come out of a pool. Thus, you can get the price of a Uniswap trade in advance, and use it as a price reading for a token.

The danger of using any on-chain price feed, is attackers can manipulate the price (see this Twitter thread with Uniswap for more). Consider the scenario:

  1. Attacker takes out ETH position with 10x leverage, going short (believing ETH will decrease in price).
  2. Attacker makes trade on Uniswap, selling ETH, reducing the ETH price by 2%.
  3. Attacker's position is now stronger due to the price change. They close their position and receive 120% their collateral.
  4. Attacker makes the reverse trade on Uniswap, buying their ETH back.
  5. Attacker makes a profit of their 120% collateral, minus the Uniswap trading fees of 0.3%.

Now there is one major impediment to this attack - it requires a very large trade to shift the price of the ETH pair on Uniswap. While that trade is recouped (save for the trading fee), it is spare capital that many don't have....unless?

Enter: flash loans

Flash loans are the coolest thing out there in decentralized finance. From the wonderful folks at Aave Protocol (if you ever get a chance, say g'day to Jordan; great guy), flash loans are the key ingredient to the bZX hack. And they're so simple.

Flash loans are loans, without collateral.

A flash loan is requested, issued, and paid back, all in one transaction. There's no collateral requirement because the loan itself doesn't really exist. As soon as the tokens are loaned, they're used and then paid back. Otherwise the transaction fails and the loan was never created in the first place. The only requirement is payment of a very small fee, and you can lend insane amounts.

The steps to making $300,000 from bZX

Getting a decentralised loan is cool, but you know what's cooler? Getting a decentralised loan of a million dollars.

Transaction 0xb5c8bd9430b6cc87a0e2fe110ece6bf527fa4f170a4bc8cd032f768fc5219838.

  1. Get a flashloan of 10,000 ETH ($1,000,000) from dYdX.
  2. Lend 50% on Compound, 50% on bZX.
  3. Borrow 112 WBTC from Compound, using the ETH collateral in #2.
    i. WBTC is a very low-liquidity coin, owing to its small supply. This means it's very easy to manipulate in price.
  4. Short WBTC on bZX with 2500 ETH, 5x leverage.
  5. Sell 112 WBTC on Uniswap, push down the price.
  6. Close position, make profit.
  7. Withdraw ETH from Compound/bZX and repay loan.

Copied from @orm12345 in r/ethtrader

And that's how the hacker (in the ingenious sense of the word) made $300,000 for the sum total of $9 in tx fees.

The pending investigation from bZX.

So far, bZX are doing their own internal investigation. There are claims they aren't using Uniswap, which is true. They aren't using it directly. Instead, in BzxOracle, they call the Kyber Network to get an expected rate (ie. price).

"Various updates and improvements" is the new "oops I killed it"

Kyber is a liquidity network, which means it connects multiple sources of liquidity from 0x, Uniswap, etc.....oh.

getExpectedRate likely calls into Uniswap. And because WBTC is such low liquidity, . You can't tell from Kyber's docs, or code, because their actual Uniswap integration is half-deployment half-approved-by-a-DAO-in-idk-when. So I'm going to leave it up to the sleuthers - their UniswapReserve bridge is deployed at 0x31e085afd48a1d6e51cc193153d625e8f0514c7f.

Conclusion

I hope you enjoyed this as much as I did. For many of us, it's the first visceral introduction into a couple of things - trusting DeFi protocols blindly, the assumption-breaking power of flash loans (what, I can lend $1M??), and watching chaotic neutral hackers reap a real profit (that's more than a bug bounty).