This technical research report was written by Polaris from the ScaleBit research team, with special thanks to Norman and Henry from SnapFingers for their revision comments.
TL;DR
This article conducts an in-depth study of the diversity and application scenarios of DeFi leverage, analyzes vulnerabilities at the code level in detail, and proposes key security points of leverage protocols.
Introduction to DeFi Leverage
The recent launch of dYdX V4 has generated a lot of attention and participation in perpetual contracts exchanges. dYdX has successfully applied leverage trading cases, and we should not only look forward to the huge potential of dYdX V4, but also pay attention to the security of the leverage protocol. Next, we will use specific code analysis and examples to familiarize you with different leverage strategies and security considerations.
what is leverage
In finance, leverage is a strategy that relies on borrowing funds to increase the potential return on an investment. Simply put, an investor or trader borrows funds to increase exposure to a specific type of asset, project, or instrument far beyond what could be achieved relying solely on their own capital. Typically, through the use of leverage, investors are able to amplify their purchasing power in the market.
Leverage in DeFi Trading
The use of leverage is one of the most important and common features in crypto asset trading. Shortly after the founding of decentralized exchanges, trading with leverage became increasingly popular, even though the crypto market already exhibited high levels of volatility.
As with traditional finance, traders use leverage either simply to borrow funds to increase their purchasing power or to take advantage of various financial derivatives such as futures and options.
Leverage has also increased from 3x, 5x to over 100x. Higher leverage means higher risk, but as seen with most centralized exchanges, as leverage trading volume grows, this is a risk that aggressive traders looking for higher returns are willing to take.
Detailed explanation of leverage classification
As far as DeFi is concerned, leveraged products are mainly divided into four types, with different mechanisms for generating leverage: leveraged lending, margin trading leverage, perpetual contract leverage, and leveraged tokens.
Leverage lending
DeFi borrowing and lending is one of the earliest and largest DeFi applications, and giants such as MakerDao, Compound, AAVE, Venus, etc. are already operating in the market. The logic of gaining leverage by lending crypto assets is simple.
For example, if you hold $10,000 in Ethereum (ETH) and are bullish, you can deposit your ETH into Compound as collateral, lend out $5,000 in USDC, and then trade that $5,000 in USDC for another $5,000. of ETH. This will give you 1.5x leverage on ETH, giving you $15,000 of ETH exposure compared to your initial $10,000 of capital.
Likewise, if you are bearish, you can choose to deposit stablecoins and lend out ETH. If the price of ETH drops, you can buy ETH on the market at a lower price and pay off the debt.
It is important to note that since you will be borrowing from a decentralized protocol, you may be liquidated if the value of the collateral drops or the value of the asset you are borrowing exceeds a certain threshold.
Margin trading leverage
With DeFi lending, you can do whatever you want with these digital assets. DeFi margin trading focuses more on increasing position size (increasing purchasing power) and is considered a true “leveraged position.” However, there is an important difference – while a margin position remains open, the trader’s assets act as collateral for the borrowed funds.
dYdX is a well-known decentralized margin trading platform that allows a maximum leverage of 5x. In margin trading on dYdX, traders use their own funds as collateral, amplifying their original principal several times and using these amplified funds to make larger investments.
Traders are required to pay interest charges and fees associated with trading. The position is not constructed virtually, it involves actual borrowing and buying/selling.
If the market moves in an adverse direction, the trader's assets may not be able to fully repay the borrowed money. To prevent this from happening, the protocol will liquidate your position before reaching a certain liquidation ratio.
How does leverage change in margin trading——
Let’s say you are 3x long on ETH on margin, but are unwilling to adjust your exposure from time to time.
You hold $100 in USDC, borrow another $200 in USDC, and trade $300 in ETH to establish the desired long position in ETH. The leverage level is $300 / $100 = 3x.
If the price of ETH increases by 20%, your profit will be 300 (1+20%) - 300 = $60. Your risk relative to liquidation is lower, and the actual leverage level is reduced to 360/(360-200) = 2.25x. In other words, you automatically de-lever when the price of ETH rises.
If the price of ETH drops by 20%, your loss will be 300 (1-20%) -300 = -$60. You are in a more risky position when it comes to liquidation, and the actual leverage level automatically increases to 240/(240-200) = 6x. In other words, you rebalance your leverage when the price of ETH drops, indicating that you are in a higher risk position than before.
So while you might think that by trading at a fixed 3x margin, you're maintaining constant leverage, real-time leverage is constantly changing. Check out the chart below to see how leverage will change based on price changes[1].
Perpetual Contract Leverage
Perpetual contracts are similar to traditional futures contracts, but have no expiration date. Perpetual contracts mimic the margin-based spot market and therefore trade close to the underlying reference index price.
There are many DeFi projects that offer perpetual contracts to traders, such as dYdX, MCDEX, Perpetual Protocol, Injective, etc. Many traders may have a hard time distinguishing the difference between margin trading and perpetual contracts – in fact, they both involve the user’s leverage.
However, there are some differences in leverage mechanisms, fees and leverage levels.
Perpetual contracts are derivatives that trade synthetic assets and have the characteristics of being traded on margin. The underlying asset price is tracked in a synthetic manner without the need to trade the actual underlying asset. However, margin trading involves actual borrowing and trading of actual crypto assets.
With the emergence of perpetual contracts, the concept of funding rates emerged, whose purpose is to keep the trading price of perpetual contracts consistent with the underlying reference price. **If the contract price is higher than the spot price, longs will pay shorts. **In other words, traders need to constantly pay fees for borrowing money.
Leverage in perpetual contracts is typically higher than in margin trading and can be as high as 100x. Liquidation and real leverage mechanisms are the same as for margin trading.
Leveraged Tokens
Leveraged tokens are derivatives that provide holders with leveraged exposure to the cryptocurrency market without the worry of actively managing a leveraged position. While they provide holders with leveraged exposure, they do not require them to deal with margin, liquidation, collateral or funding rates.
The biggest difference between leveraged tokens and margin trading/perpetual contracts is that leveraged tokens will be rebalanced periodically or when a certain threshold is reached to maintain a specific leverage.
This is obviously different from margin trading and perpetual contracts - the actual leverage of these products constantly changes based on price movements, even though the trader may have originally specified a leverage level.
Let’s look at how rebalancing works in the 3x ETH example above:
You hold $100 USDC and buy an ETHBULL (3x) leveraged token. The protocol will automatically borrow $200 USDC and trade $200 ETH.
Let’s say the price of ETH increases by 20% and the ETHBULL (3x) token price rises to 300*(1+20%)-200 = $160 before rebalancing. Now, your actual leverage becomes 2.25 (360/160), which is lower than the target leverage.
As part of the rebalancing process, the protocol will borrow more USD from the stablecoin pool and purchase additional ETH tokens to move leverage back to 3x. In our example, the protocol will borrow another $120 and exchange it for ETH. Therefore, the total leverage again becomes (360+120)/160 = 3 times.
Let’s say the price of ETH drops by 20% and the ETHBULL (3x) token price drops to 300*(1-20%)-200 = $40 before rebalancing. Now, your actual leverage will become 6 (240/40), which is higher than the target leverage.
In this case, the protocol will sell ETH tokens and repay outstanding debt to reduce leverage. In this example, the protocol will sell $120 of ETH to pay the pool. The debt will become $80 and the total leverage is again (240-120)/40 = 3x.
In other words, leveraged tokens will automatically re-leverage on profits and deleverage on losses to restore their target leverage levels. If this mechanism works well, even in adverse market trends, leveraged token holders will not be liquidated because the deleveraging mechanism will continuously reduce the user’s effective leverage level.
Therefore, lending pools in a leveraged token model will be free from liquidation risk and are safer than lending pools in margin trading.
Leverage application cases
We have already learned about some common DeFi protocol types of leverage. Next, we will explain the application of leverage in detail based on specific DeFi protocols.
GMX
GMX [2] is a decentralized spot and perpetual exchange that provides traders with the ability to trade assets with up to 50x leverage. The protocol currently runs on Arbitrum and Avalanche. On GMX, traders have full knowledge of their counterparties, which is completely different from trading on CEX. GMX differs from other perpetual contract protocols such as dYdX in that it operates entirely on-chain and uses AMM functionality to enable leveraged trading.
What sets GMX apart from other services is that it is a decentralized exchange that offers leveraged trading services. In this regard, it combines an experience similar to other DeFi exchanges like Uniswap with leveraged trading services offered by the likes of Binance.
GMX has a liquidity pool, GLP, which is a multi-asset pool that provides liquidity for margin trading: users can go long/short and execute trades by minting and burning GLP tokens. The pool earns LP fees from trading and leveraged trades, which are distributed to GMX and GLP holders.
In order to trade with leverage, traders deposit collateral into the protocol. Traders can choose leverage up to 50x. The higher the leverage, the higher the liquidation price, which will gradually increase as borrowing fees increase.
For example, when going long ETH, a trader is "renting" the upside of ETH from the GLP pool; when going short ETH, the trader is "renting" the upside of the stablecoin relative to ETH from the GLP pool. But the assets in the GLP pool are not actually leased.
When closing a position, if the trader bets correctly, profits will be paid out from the GLP pool in the form of long tokens; otherwise, losses will be deducted from the collateral and paid into the pool. GLP profits from traders' losses and profits from traders' profits.
In the process, traders pay trading fees, opening/closing fees, and borrowing fees in exchange for the upside of going long/short against the U.S. dollar on designated tokens (BTC, ETH, AVAX, UNI, and LINK).
Merkle Trade
Merkle Trade[3] is a decentralized trading platform that offers cryptocurrency, foreign exchange and commodities trading with leverage up to 1,000x and advanced user-centric trading features. Merkle Trade is powered by the Aptos blockchain, offering best-in-class performance and scalability. Compared with Gains Network, it has lower transaction delays and handling fees while providing the same high leverage.
Unlike most exchanges, there is no order book on Merkle Trade. Instead, Merkle LP acts as a counterparty on every trade, collects collateral when traders lose money, and pays out profits on closed trades with positive returns.
Trade cryptocurrencies, forex and commodities with up to 1,000x leverage
Merkle Trade aims to offer a wide range of trading pairs from day one, including cryptocurrencies, FX and commodities, and offers some of the highest leverage on the market; up to 150x on crypto and 1,000x on FX.
Fair-priced order execution, millisecond latency, minimal slippage
Powered by the lowest-latency Aptos-generated blockchain to date, the fastest on-chain transaction experience possible. For traders, this means a faster trading experience with less price slippage due to execution delays.
Decentralized, non-custodial trading with no counterparty risk
Traders trade with a liquidity pool (Merkle LP) that acts as the counterparty to every trade on the protocol. All transactions and settlements are executed by smart contracts, and there is no custody of user funds at any time.
Minimum handling fee
Merkle Trade claims to have one of the lowest fees on the market to date. At launch, fees are as low as 0.05% for cryptocurrency trading pairs and as low as 0.0075% for FX trading pairs.
dYdX
dYdX[4] is a decentralized exchange (DEX) that gives users the ability to efficiently trade perpetual contracts while fully controlling their assets. Since its launch in 2021, dYdX V3 has adopted a unique non-custodial layer 2 scaling solution to implement its exchange, but its order book and matching engine are still managed centrally.
And now, with dYdX V4, the protocol is evolving into its own chain and completely refactoring the entire protocol to achieve full decentralization while increasing throughput. dYdX also includes three functions: lending, margin trading and perpetual contracts. Margin trading comes with a borrowing function. The funds deposited by users automatically form a fund pool. If there are insufficient funds during the transaction, they will automatically borrow and pay interest.
Leverage Security Analysis
We have introduced the common types and applications of leverage in DeFi. Similarly, there are still many security issues in the design of leverage that deserve our attention. We will analyze the security issues and audit points of DeFi leverage with specific audit cases.
Distinguish between limit and market orders
In most leveraged exchange applications, there are limit orders and market orders, and it is necessary to strictly distinguish and verify limit orders and market orders. Next, we will conduct a detailed analysis of the problems we found in the Merkle Trade audit [5].
let now = timestamp::now_seconds(); if (now - order.created_timestamp > 30) { cancel_order_internal<PairType, CollateralType>( orderid, order, T_CANCEL_ORDER_EXPIRED ); return };
This part of the code is to perform verification in the order function. In this function, it checks whether more than 30 seconds have passed since the order was created. If the conditions are met, cancel_order_internal() is called to cancel the order. However, if the order is a limit order, it means that the order has a specific price set by the trader at which they are willing to buy or sell the asset. This judgment should not be used when executing limit orders, which may result in most limit orders not being executed. Therefore, it is important to strictly distinguish the trading logic of limit orders and market orders.
Leverage calculation error
Calculation errors have always been a very common problem in DeFi, and they are especially common in leverage. We will use the problems found in third-party audits of the Unstoppable[6] protocol to conduct an in-depth study of the calculation of leverage.
Let’s look at the code in Unstoppable that calculates leverage:
def calculateleverage( positionvalue: uint256, debtvalue: uint256, marginvalue: uint256 ) -> uint256: if positionvalue <= debtvalue: # bad debt return max_value(uint256) return ( PRECISION * (_debt_value + marginvalue) / (_position_value - debtvalue) / PRECISION ) The calculateleverage function causes the leverage to be calculated incorrectly by using debtvalue + marginvalue as the numerator instead of positionvalue. The three input parameters of this function, positionvalue, _debt_value and marginvalue, are all determined by the price information provided by the oracle on the Chainlink chain. where _debt_value represents the value of converting the position's debt share into a USD debt amount. _margin_value represents the current value (in USD) of the initial margin amount of the position. _position_value represents the current value (in USD) of the initial position amount of the position.
The problem with the above calculation is that debtvalue + marginvalue does not represent the value of the position. Leverage is the ratio between the current position value and the current margin value. _position_value - debtvalue is correct, it represents the current margin value, but debtvalue + marginvalue does not represent the current value of the position, because there is no guarantee that the liability token and the position token will have related price fluctuations.
for example:
The liability token is ETH and the position token is BTC.
Using 1 ETH as margin, Alice borrows 14 ETH ($2,000 per ETH) and receives 1 BTC ($30,000 per BTC) in position tokens. Leverage is 14.
The next day, the price of ETH was still $2,000/ETH, but the price of BTC dropped from $30,000/BTC to $29,000/BTC.
At this point, the leverage should be (_position_value == 29,000)/(_position_value == 29,000 - debtvalue == 28,000) = 29
Instead of the value calculated in the contract: (_debt_value == 28,000 + marginvalue == 2,000) / (_position_value == 29,000 - debtvalue == 28,000) = 30.
Therefore, in order to fix this issue, the correct formula mentioned above should be used to calculate leverage in smart contracts. Leverage calculation errors can lead to unfair liquidations or over-leveraged positions in the event of price volatility.
In smart contracts, ensuring correct leverage calculations is critical to maintaining the robustness of the system and the interests of users. The correct leverage calculation should be based on the ratio between the current value of the position and the current margin value. If an incorrect calculation formula is used, it may cause the system to respond inappropriately to price changes, liquidate positions that should not be liquidated, or allow over-leveraged positions to continue to exist, thereby increasing the risks to the system and users.
logical error
Logic errors require special attention in the audit of smart contracts, especially in complex logic such as DeFi leverage transactions.
Let us use the problems found in third-party audits by Tigris[7] (Tigris is a decentralized synthetic leverage trading platform based on Arbitrum and Polygon) to discuss the logical issues that need to be paid attention to in DeFi leverage.
Let’s look at the logic of the limit closing function in Tigris:
function limitClose( uint id, bool tp, PriceData calldata priceData, bytes calldata signature ) external { checkDelay(id, false); (uint limitPrice, address tigAsset) = tradingExtension._limitClose(_id, tp, priceData, signature); closePosition(_id, DIVISION_CONSTANT, limitPrice, address(0), tigAsset, true); } function limitClose( uint id, bool tp, PriceData calldata priceData, bytes calldata signature ) external view returns(uint limitPrice, address tigAsset) { checkGas(); IPosition.Trade memory trade = position.trades(id); tigAsset = trade.tigAsset; getVerifiedPrice(_trade.asset, priceData, signature, 0); uint256 price = priceData.price; if (_trade.orderType != 0) revert("4"); //IsLimit if (_tp) { if (_trade.tpPrice == 0) revert("7"); //LimitNotSet if (_trade.direction) { if (_trade.tpPrice > price) revert("6"); //LimitNotMet } else { if (trade.tpPrice < price) revert("6"); //LimitNotMet } limitPrice = trade.tpPrice; } else { if (trade.slPrice == 0) revert("7"); //LimitNotSet if (_trade.direction) { if (_trade.slPrice < price) revert("6"); //LimitNotMet } else { if (trade.slPrice > price) revert("6"); //LimitNotMet } //@audit stop loss is closed at user specified price NOT market price limitPrice = _trade.slPrice; } }
When using stop loss to close a position, the user's closing price is the stop loss price set by the user, not the current price of the asset. In directional markets and high leverage, users may abuse this to achieve virtually risk-free trading. Users can open a long position and set a stop loss price that is $0.01 below the current price.
If the price drops immediately in the next update, they will close the position at their entry price and only pay opening and closing fees. If prices rise, they stand to gain significantly. As a result, users can abuse the stop-loss price setting method to open transactions with high leverage, high upside potential, and low downside risk.
price fluctuations
The impact of price fluctuations on DeFi leverage is very important. Only by always considering price fluctuations can you ensure the safety of the leverage agreement. Let us take the problems found in the third-party audit of the DeFiner[8] protocol as an example for in-depth analysis:
The DeFiner protocol performs two checks before processing withdrawals.
First, the method checks whether the amount requested by the user to withdraw exceeds the balance of the asset:
function withdraw(address accountAddr, address token, uint256 amount) external onlyAuthorized returns(uint256) { // Check if withdraw amount is less than user's balance require(amount <= getDepositBalanceCurrent(_token, accountAddr), "Insufficient balance."); uint256 borrowLTV = globalConfig.tokenInfoRegistry().getBorrowLTV(token);
Second, the method checks whether withdrawals would leave the user with too much leverage. The amount withdrawn is subtracted from the user's "borrow power" of the current price. If the user's total borrowing value exceeds the new borrow power, the method fails because the user no longer has enough collateral to back his borrowing position. However, this require will only be checked if the user is not already over-leveraged:
if (getBorrowETH(_accountAddr) <= getBorrowPower(_accountAddr)) require( getBorrowETH(_accountAddr) <= getBorrowPower(_accountAddr).sub( amount.mul(globalConfig.tokenInfoRegistry().priceFromAddress(token)) .mul(borrowLTV).div(Utils.getDivisor(address(globalConfig), _token)).div(100) ), "Insufficient collateral when withdraw.");
If a user has borrowed more than their "borrow power" allows, withdrawals can be made regardless. This situation can occur in a variety of situations, the most common being price fluctuations. The protocol did not take into account the impact of price fluctuations on the protocol, which caused this problem.
other
In addition to the above-mentioned failure to differentiate between limit orders and market orders, calculation errors, logic errors, and the impact of price fluctuations, there are many safety points related to leverage agreements that we need to pay attention to. This includes but is not limited to issues such as flash loan attacks, price manipulation, oracle security, access control, insufficient or lack of strict leverage checks, and other issues. When designing and implementing a leverage protocol, these factors must be carefully and carefully considered to ensure the robustness of the protocol and the security of user assets. Preventative measures, real-time monitoring and emergency response plans are also key to reduce potential risks and protect user interests.
Summarize
The introduction of leverage trading in DeFi protocols does provide the market with greater operability, but also brings more complex trading mechanisms. Although leveraged trading provides users with more investment opportunities, its potential risks and challenges to protocol security have also become more significant.
As leverage increases, the operation of the protocol becomes more flexible, but it also becomes more fragile and susceptible to various security threats. This includes the potential for not strictly distinguishing between limit and market orders, calculation errors, logic errors, and extreme sensitivity to factors such as price fluctuations. In this case, we must pay more attention to the security of the protocol to ensure that users’ assets are effectively protected.
ScaleBit is a leading blockchain security team in the Web3 field, located in Silicon Valley, Singapore, Hong Kong, Taiwan and other places. We have provided blockchain security solutions to 200+ institutions and projects in the global Web3 field, audited a total of 180,000+ lines of code, and protected user assets of more than 8 billion+ US dollars. Make Security Accessible for All! If you have any security audit needs, please feel free to contact us. We will customize detailed, comprehensive, and professional security solutions for you to protect you and the Web3 field!