Existing decentralized finance (DeFi) lending protocols grapple with vulnerabilities, especially during rapid market shifts that can render loans insolvent before they can be liquidated. The Solvent Lending protocol addresses this by using Interest Accruing Stop Loss Orders (IASLOs), a new type of hook on top of Uniswap v4 liquidity pools. This mechanism ensures that liquidations always happen when they are supposed to, even during significant market fluctuations. This whitepaper presents Solvent Lending’s design and compares its robustness to existing DeFi lending systems, highlighting its potential to enhance stability and decentralization in DeFi.
Whitepaper version:
In the evolving DeFi ecosystem, decentralized finance has faced notable vulnerabilities. One important issue is loans becoming insolvent before liquidators can intervene, especially during sudden market shifts. This not only places lending protocols at risk but also diminishes trust in DeFi platforms. Solvent Lending proposes a novel solution. This paper introduces a new DeFi primitive, the Interest Accruing Stop Loss Order (IASLO), to be integrated with Uniswap v4 liquidity pools as a set of hooks. Using these IASLOs, Solvent Lending ensures timely liquidations regardless of market conditions. This whitepaper details the design of Solvent Lending, contrasting its strengths against existing DeFi lending methods, and underscores its potential to bolster stability, security, and decentralization in DeFi.
DeFi lending protocols allow users to collateralize ERC-20 tokens, leveraging them to borrow other tokens. At the heart of these systems is a mechanism to manage the risk of volatile asset values. When collateral asset values plummet, loans risk insolvency, leading to losses for the protocol or its users.
Traditionally, these lending protocols have incorporated liquidators, third-party participants who repay loans when the ratio between the value of their borrowed tokens and their collateral falls such that they become liquidatable. The liquidators receive a liquidation bonus, thus taking over the collateral at a profit. The caveat here is that rapid market shifts can outpace these liquidators, resulting in insolvent debt on the lending protocol’s balance sheet. These insolvent loan positions are backed by collateral assets that are worth too little to cover the outstanding tokens lent out to borrowers. Ultimately this shortfall must be covered by the protocol itself or by its users.
In practice, most liquidators are bots programmed to periodically check for profitable liquidation opportunities. When they find one they take out a flashloan,1 borrowing the borrowed token, liquidating the lending position, swapping back to the borrowed token on a decentralized exchange (DEX), and then repaying the flashloan. The liquidator’s profit is the value of the liquidation bonus minus all costs (gas fees, DEX swap fees, flashloan fee).
DEX liquidity is a crucial element in the liquidation process. Liquidators cannot rely on centralized exchange (CEX) liquidity because it cannot be incorporated into an atomic transaction.2 If there’s any delay in swapping tokens, the liquidation cannot be financed via flashloan. Liquidations without flashloans would require liquidator bots to hold enough tokens to liquidate positions themselves, and carrying a large enough balance for the largest and most profitable liquidations would impose high capital costs and risk.
Despite DEX liquidity being so crucial, current lending protocols cannot rely on it to exist when they need it. Liquidity providers can withdraw the tokens necessary to liquidate all outstanding loans, and the lending protocol has no smart-contract-enforced claim to those funds.
Until now. With the advent of Uniswap v4 and its “hooks,” there is an opportunity to directly intervene in the contract execution process at specific junctures, paving the way for more dynamic solutions to the liquidation challenge.
In this backdrop, we introduce Solvent Lending, a DeFi lending protocol that employs Uniswap v4 hooks. We introduce the Interest Accruing Stop Loss Order (IASLO), a new hook type designed to guarantee liquidations happen when relative token prices cross specific thresholds.
A quick background on Uniswap is essential to understand Solvent Lending. Uniswap is a DEX that allows users to swap different crypto tokens based on the constant product formula, x × y = k where x is the value of one token, y is the value of the other token, and k is a constant. This means, for example, that if there are 10 times as many of token A as there are of token B, the price of B must be ten times A.
Users supply liquidity to the pool by depositing both tokens, and the pool contract accepts any incoming trade that pays the required price plus a small fee. The fee rate varies between pools but is most commonly set to 0.3% of the trade value.
Uniswap v2 used a single pool to manage all liquidity, spreading it across a continuous price range from 0 to infinity. Uniswap v3, however, introduced the concept of "ticks" to partition this price space into discrete segments, turning it into a piecewise linear function. Each tick represents a fixed price and serves as a bucket where liquidity can be concentrated. Liquidity providers can choose upper and lower ticks to specify the price boundaries of their position. The benefit of this mechanism is that it allows for improved capital efficiency, particularly when liquidity is concentrated around a specific price range. For example, in pools for swapping USD-pegged stablecoins, liquidity is often most useful when concentrated between ticks corresponding to prices from 0.99 to 1.01.
The most significant advancement from Uniswap v3 to Uniswap v4 is the introduction of "hooks," which are calls to external smart contracts that are executed either before or after specific actions are taken by users. These actions include initializing a pool, modifying a liquidity position, swapping tokens, or donating tokens. These hooks are crucial for the functionality of Solvent Lending.
Solvent Lending has two parts: IASLOs implemented as Uniswap v4 hooks, and the lending protocol itself, which relies on the IASLOs for liquidations.
A stop-loss order is an order to sell an asset when its price falls to a certain value. It is the mirror image of a limit order, an order to buy (sell) an asset when it falls below (rises above) some price. But while stop losses and limit orders are superficially similar, there are important differences that make stop losses more difficult to implement.
Limit orders buy when traders are selling and sell when traders are buying. The trades that move prices to the limit price can also be used to fill the orders. They provide additional liquidity for the traders willing to take the other side of the order.
Stop losses sell when traders are selling and buy when traders are buying. This means that they compete with traders for liquidity. This imposes a constraint on stop losses: the liquidity pool must have sufficient liquidity to fill all stop-loss orders alongside the trades that trigger them. This means that some liquidity must be locked up to fulfill stop-loss orders. This lockup is an implicit cost on liquidity providers, who must be compensated with interest payments.
An IASLO is a stop-loss order that accrues interest to be paid to liquidity providers (and possibly other parties). The position accrues potential interest continuously. This interest can be realized, either by the user paying interest from a pool of tokens they have set aside or by the position moving to a higher price tick. Every tick must always have enough liquidity to fill all stop-loss orders at the tick’s price, and these orders must be automatically triggered by any swap that moves the price into the tick.
One thing worth noting is that IASLOs have utility outside of the context of Solvent Lending, and nothing prevents any user or smart contract from using them once deployed. The simplest use case is for traders to prevent excessive losses on their assets.
The IASLO smart contract features a ledger with all outstanding stop-loss orders, and their associated ticks and interest rates. It features the following functions.
open_new_stop_loss()
allows the user to open a new
stop-loss order if there is sufficient liquidity in the relevant price
ticks.
change_external_interest()
allows the user to change
the additional interest accrued by the position. IASLOs pay interest to
liquidity providers, and they can optionally pay additional interest to
a third party (e.g. a lending pool).
close_stop_loss()
allows the user to repay the
outstanding interest on an open stop-loss order and close the order or
collect the exchanged tokens if the stop loss has been
executed.
deposit_to_interest_reserve()
allows the user to add tokens
to an interest reserve vault. These tokens are used to pay interest as it
accrues.
withdraw_from_interest_reserve()
allows the user to remove
tokens from an interest reserve vault.
realize_interest()
initiates the payment of accrued
interest using tokens from an interest reserve vault. If the vault is empty or
contains insufficient funds, the function will move the stop-loss order to a
higher price tick. Should the stop-loss order be executed at this new, higher
price tick, any additional tokens that are purchased due to the higher price
will be allocated to settle the interest owed by the position.
disburse_interest()
calls the donate()
function of the Uniswap v4 pool to pay accrued interest owed to
liquidity providers. Pays out additional interest to the address specified by
the user.
The IASLO contract’s base interest rate is a variable rate based on the ratio of stop-loss orders in a tick and the amount of liquidity in that tick. If a high fraction of total liquidity is tied up in stop loss orders, the interest rate may be very high, encouraging users to add additional liquidity to cover all orders and allow other users to make withdrawals.
When initializing an IASLO-enabled liquidity pool, it must be connected to the IASLO smart contract via two hooks:
Before a swap transaction is executed, a hook calls the IASLO smart contract. This hook checks if the swap has moved the price through one or more new price ticks. If there are stop-loss orders associated with those ticks, they are added to the swap and executed as a batch alongside it.
Before a user modifies their liquidity position, a hook calls the IASLO smart contract and checks if this change would reduce liquidity below the amount needed to fulfil all stop loss orders in all affected ticks.
Solvent Lending allows users to deposit tokens as collateral and borrow other tokens, deposited by other users, against them. It features the following functions.
add_token_pair()
creates a new lending pool linked
to an IASLO-enabled Uniswap v4 pool. When creating the pair, the user
sets fixed parameters, such as the interest rate curve.
deposit()
allows users to deposit ERC-20 tokens as
collateral into specific token pairs. Depositors earn interest on their
tokens when they are borrowed.
withdraw()
enables depositors to withdraw their
tokens. This function checks if there is sufficient liquidity in the
protocol to fulfill the withdrawal without affecting outstanding loans.
If not, the request will be queued until liquidity is
available.
borrow()
lets users open a borrow position with
their collateral tokens. The collateral is deposited into an IASLO at
the price ratio that would make its value equal to that of the borrowed
tokens.
repay_loan()
allows borrowers to repay their
borrowed amount plus any accumulated interest. Repayments can be partial
or full.
liquidate_borrow()
resolves a liquidation after it
has been triggered by the IASLO contract, marking the position as
closed.
collect_interest()
takes any interest accrued from
borrowers and distributes it to token depositors, rewarding them for
providing liquidity.
update_interest_rate()
adjusts the interest rate of
a token pair and passes it to the IASLO contract. The interest rate is
an increasing function of the ratio of tokens available to lend and
tokens borrowed.
update_protocol_fee()
adjusts the fraction of
interest accruing to the protocol. This action can only be performed by
the protocol owner. The default fee rate is 0%.
set_protocol_fee_recipient()
changes the address
protocol fees are sent to. This action can only be performed by the
protocol owner.
collect_protocol_fees()
sends accumulated protocol
fees for a specific pool to the protocol fee recipient.
The interest rate curve is an increasing function of the ratio of tokens available to lend and tokens borrowed. In contrast to other lending protocols, tokens used as collateral cannot be lent out, as they are locked into the IASLO contract. Tokens being used as collateral do not accrue interest.
Alice wants to borrow USDC using ETH as collateral.
Alice first chooses a token pair, in this case, ETH-USDC. The pair is associated with an IASLO-enabled Uniswap v4 pool.
Alice deposits 10 ETH using the deposit()
function. This
ETH will serve as her collateral.
After depositing her ETH, Alice uses the borrow()
function to take out a loan of USDC. There is effectively no limit on
how leveraged Alice can get. In the extreme case, she can borrow almost
the total value of her ETH in USDC, with her liquidation price one tick
below the current price tick. Alice chooses a leverage position based on
her personal risk appetite. In this transaction, Alice also deposits a small
amount of USDC into her interest reserve vault to cover future interest
payments. The minimum deposit required is determined by the pool parameters.
As time progresses, the interest on the borrowed USDC accumulates.
Some of the interest accrues to liquidity providers in the Uniswap v4
pool via the IASLO smart contract. The other portion of interest accrues
to users who provide the USDC tokens in a Solvent Lending
pool. This interest rate adjusts dynamically based on the demand for
borrowing, and the available supply of USDC in the pool, periodically
passed to the IASLO contract by the update_interest_rate()
function. If Alice keeps her position open for a long time, or if interest
rates are particularly high, Alice’s interest owed may exceed the amount in her
interest reserve vault. If this is the case, her position may need
to move up one or more price ticks. When any user calls the
realize_interest()
function, Alice’s borrow position will be
moved to the new tick if the new tick has sufficient liquidity to fill
the stop loss order.3
After some time, Alice decides to repay her loan. She returns the
USDC she borrowed plus the accumulated interest using the
repay_loan()
function.
After repaying her loan, Alice can use the withdraw()
function to reclaim her 10 ETH, or she might leave it in the pool to
accumulate interest when borrowed by other users.
Imagine a token called VUL (Vulnerable Token) with an unknown vulnerability.
Alice deposits ETH in the Solvent Lending ETH/VUL pool. Bob deposits a significant amount of VUL and borrows ETH.
Chris, a hacker, discovers a way to mint unlimited VUL tokens. He sets up a series of transactions to extract the maximum possible value from this exploit. VUL’s price starts plummeting rapidly as Chris drains all available liquidity. Chris sells as much VUL as possible in the Uniswap v4 VUL/ETH pool. Chris’s sale moves the VUL/ETH price through the tick where Bob’s VUL becomes liquidatable.
Chris’s transaction in Uniswap v4 triggers the hook that calls the IASLO contract. Since the price is passing through Bob’s liquidation price tick, a VUL → ETH swap is added to Chris’s transaction for the amount of ETH Bob owes. These ETH tokens are set aside to be collected by the Solvent Lending contract.
Any user can call Solvent Lending’s liquidate_borrow()
function on Bob’s borrow position. This returns the liquidated ETH to
the pool and marks Bob’s position as closed. Alice can withdraw the ETH
she contributed to the pool plus interest since Bob’s position was
safely liquidated.
In traditional DeFi platforms, there’s a range of prices between the price that makes a borrow position liquidatable and the price that makes it insolvent and unable to be liquidated profitably. The price must stay in this range long enough for liquidators to repay the loans. If prices fall through this range very quickly, as they do in the case of an exploit, it may not be possible for liquidators to liquidate all debt positions, leaving the protocol with insolvent debts. With Solvent Lending’s integration of IASLO, the system is able to liquidate all borrow positions in the same transactions that cause prices to fall, ensuring the protocol remains solvent.
Solvent Lending works in a substantially different way from existing protocols, so it has both advantages and disadvantages.
As we saw in the exploited token example above, Solvent Lending does not take losses when a bad token is added as collateral. Because of this, any token pair can be added to the protocol by a user without the need for permission or a governance vote. A token can be launched and have an on-chain lending market on the same day.
Solvent Lending allows users to borrow such that they would be liquidated at any price tick below the current one, so long as there exists sufficient liquidity in the tick to liquidate all positions. Existing lending protocols must limit borrowing to a fraction of collateral value to give liquidators a window of prices in which to liquidate. Solvent Lending's IASLO-based liquidation mechanism does not require this.
The IASLO and Solvent Lending contracts are non-upgradeable. All the parameters for a lending pool are set when it is initialized and cannot be changed.
Solvent Lending relies only on the token balances of the underlying IASLO-enabled Uniswap v4 pools for liquidations. It does not require any price oracles, on-chain or off-chain.
Solvent Lending uses IASLO hooks to automatically liquidate debt positions when trades cause prices to move. Traders have a natural incentive to arbitrage away price differences between different exchanges, so they don’t need an additional bonus to incentivize them to make trades that trigger liquidations.4
In existing protocols, a user’s collateral tokens go into a big pool and a fraction of them are lent out to other users. IASLOs require the collateral tokens to be locked in the IASLO contract, so they cannot contribute to the pool of loanable tokens. A user who wants to earn interest on his tokens in Solvent Lending cannot simultaneously use them as collateral.
In existing protocols, a user can use one or more collateral tokens to borrow one or more other tokens. Solvent Lending only allows for one-to-one borrowing. A user may have many borrow positions, but each one has a separate liquidation price associated with a specific Uniswap v4 pool.
The project of DeFi is to create robust and decentralized systems allowing anyone access to finance without permission or gatekeepers. But while users can trade tokens permissionlessly, the current generation of lending protocols are simply too risky to allow permissionless lending and borrowing. They require active risk management to avoid catastrophic losses.
Solvent Lending is the first permissionless lending market for DeFi. It achieves this by having a liquidation mechanism that is robust to any price change of the underlying tokens. It has no external dependencies: no governance, no price oracles. Once deployed on-chain, it can conceivably function for as long as the underlying chain continues to operate. This is not just a step, but a leap forward for DeFi, presenting a paradigm where trust is in the code and resilience is inherent. Solvent Lending epitomizes the true spirit of DeFi, marrying security with absolute decentralization. The future of lending in DeFi might just be solvent by default.