Protect NFT Borrowers and Lenders via Dutch Auction Liquidations

We balance competing interests in a borrower liquidation auction via Dutch Auction with novel characteristics to solve key problems for our collateralized borrowing protocol.

Why Dutch Auction - Solving a Key Problem

As a collateralized lending platform Parallel will need to create and enforce efficient liquidation methods in order to protect lenders and protocol solvency. Of course no one wants to liquidate a borrower's NFT's, and in doing so we need to ensure we achieve maximum value for the same in order to return any excess proceeds to the borrower.

With Non-Fungible Tokens (i.e. ERC-721's) this represents a challenge given their non-fungible nature which makes price discovery difficult. We have nonetheless devised a Dutch Auction with a blend of pricing models which we believe will maximize the likelihood we achieve a high selling price for the given NFT.

User Goals/Stories:

  1. As a liquidity providing user to the protocol (and member of the protocol) I want to earn yield on my capital with low risk. As a key part of this risk I want to eliminate the risk of losses if the borrower goes into liquidation. And indeed I should be able to more than cover the value of the loan if forced to sell an NFT as collateral.

  2. As a borrower I want to borrow high amounts of capital at low rates in order to improve my capital efficiency against my valuable but illiquid assets such as NFT’s. I want to avoid losing my assets, but if forced into liquidation I want to maximize the value returned to me.

NB: liquidity providers and borrowers are likely the same people at different points in time. Also it is critical to note that in times of sharp market declines we must keep in mind time is short; if we wait too long to conduct an auction prices may have moved lower thereafter.

Introduction to Dutch Auctions

A Dutch Auction is distinct from a traditional auction in which bidders place ascending bids and the highest bid wins. In a Dutch auction, the seller/auctioneer instead announces the highest ask price at the start and that ask price drops until a buyer accepts the ask price which in turn becomes the market clearing price.

Notable examples of Dutch Auctions in NFT’s include the Art Blocks collection which offers Dutch auctions in which the ask price decays linearly or exponentially.

Traditional Price Declines in Dutch Auctions

At time t0t_0 the auctioneer lists the highest ask price for the good at price p0p_0. At each time interval that price decreases by constant step ss. The minimum could be 0 in the general sense, but we would clearly never run an auction without a floor. We’ll call this pminp_{min}

With s(0,): F(t)=p0s(tt0)         \begin{alignat}{1}With \ s\in(0,\infty):\ F(t)=p_0 - s \cdot (t-t_0) \ \ \ \ \ \ \ \ \ \end{alignat} \nonumber

The minimum price is then defined as the interval tt such that pmin=p0s(tt0)p_{min} = p_0 - s \cdot (t-t_0) with which it is trivial to solve for the length of the auction tt.

The upshot: this is a model easy to understand though potentially slow in price discovery if we go at regular increments.

Exponential Price Decay in Dutch Auctions

By definition price will decay by an exponent as time progresses. We will use a function of exponents with λ\lambda to set the rate of exponential decay. (NB: for smaller values, λ% change\lambda \approx \% \ change between ptp_tand pt+1p_{t+1})

With λ(0,):   pt=p0eλ(tt0)   \begin{align}With \ \lambda \in(0,\infty): \ \ \ p_t =p_0 \cdot e^{-\lambda (t-t_0)} \ \ \ &&\end{align} \nonumber

λ\lambda determines the rate of price decay as a function of time tt. It is of course still possible to set a minimum price with the exponential decay where pmin=p0p0eλ(tt0)p_{min} = \frac{p_0}{p_0 \cdot e^{-\lambda (t-t_0)} }.

At time tmint_{min}price will remain stable at pminp_{min} until there is a successful bid. If there is no successful bid the auction will fail.

The upshot: price can converge to pminp_{min} faster in the Exponential decay function than in the case of the linear decay. Given the time-sensitivity of the auction this may indeed be preferable.

See below for the varying shapes and rates of price decay according to different inputs of λ\lambda​.

Dutch Auction of NFT with Blended Decay

Let’s remember our goal: maximize value derived from an auction to satisfy the user’s outstanding debt to the protocol/lenders such that the borrower may likewise receive the excess capital received by the auction. Or in short: we want to maximize price received.

The key challenge is price discovery in NFT’s, and our proposal is thus to begin with an exponential decay auction in order to put a high starting price p0p_0 at which price will decline exponentially until a pminexpp_{minexp} at which point the decay will become linear. We would do this in order to quickly go through the lower-probability/high-reward ‘Ask’ prices.

Moving beyond the general case and specifically into NFT's, we will define F(t)F(t) as a function of floorfloorprice multiples, or mm. This allows us to normalize prices across NFT collections where Price at time t=floormtPrice \ at \ time \ t= floor \cdot m_t. By definition the floorfloor​ of an NFT collection is the minimum 'Ask' price of any token within the collection.

Notably the floorfloor value on Para Space comes from the Time Weighted Average Price (TWAP) on-chain oracle used in the collateralized borrow calculation. Read more on our TWAP in our documentation here as measured by our TWAP oracle.

With m(mminexp, m0):   mt=m0eλ(tt0)   With m(mmin, mminexp):  mt=mt1s (tt0)With m[mmin]:  mt=mmin\begin{align}With \ m \in (m_{minexp}, \ m_0): \ \ \ m_t =m_0 \cdot e^{-\lambda (t-t_0)} &&&&\ \ \ \\ With \ m \in (m_{min}, \ m_{minexp}): \ \ m_t=m_{t-1} - s \ \cdot (t-t_0) \\ With \ m \in [m_{min}]: \ \ m_t = m_{min} \end{align} \nonumber

Let’s start with these inputs as an illustration:

m0=10λ=0.1s=0.05mminexp=2mmin=0.4\begin{align} m_0 = 10 \\ \lambda = 0.1 \\ s = 0.05 \\ m_{minexp} = 2 \\ m_{min} = 0.4 \end{align} \nonumber

If tt represents 15-minute intervals, we would reach the mminexpm_{minexp} with t=16t = 16, or 240 minutes—4 hours. And the auction would reach mminm_{min} within t=38t=38 or 9.5 hours.

Clearly the shape of this graph would change according to different values for each of these inputs.

We could steepen or flatten the exponential decay function according to different inputs, but the upshot is straightforward: we can cover more potential clearing prices and allow for greater price maximization if we kick off our Dutch auction with exponential decay

We Use Real Data to Set Auction Parameters

We always want to ground ourselves in the data. To that end we want to see the distribution of token sale prices as a function of multipliers of the floor price. Using the same NFT sales price methodology as in this paper we derive the multipliers of floor prices for the supported collections. In this case we will limit our data to the most recent 90 days of trading in order to calibrate our model for current market conditions.

Below is a box plot with the top and bottom quartiles captured by the edges of the box, the median by the line in the center of the box. The top ‘whisker’ represents the 99th percentile and the bottom ‘whisker’ the 1st percentile of all transactions.

Distribution of NFT Sales in Terms of Collection Floor Price

A brief look at the chart above emphasizes the distribution of NFT sales varies widely even among top-tier collections. Bored Ape Yacht Club NFT’s tend to trade within a fairly narrow distribution, but Otherdeeds from the Otherside NFT’s see a much wider trading range relative to the collection floor price. And indeed we will have to set custom parameters to improve our chances of efficiently finding the market-clearing price.

We Set Minimum and Maximum Prices Based on Real NFT Collection Sales

Our Dutch Auction will begin with a high starting price m0m_0 which will represent the 99th percentile of multiples of floorfloor in the sales distribution. For mminexpm_{minexp}we will in turn take the 75th percentile the remaining inputs. And for mminm_{min} we will assume we drop to the worst 1st percentile of multiples of floorfloor.

The Dutch auction price will decay exponentially between m0m_0 and mminexpm_{minexp} values while decaying linearly between mminexpm_{minexp} and mminm_{min}. Or in short—we will cycle through the more speculative top-end of the price distribution relatively quickly and switch to a slower price decay through the remainder.

Again each mm value represents the multiplier of the floorfloor price as measured by our TWAP oracle. As such our Dutch auction will by design react to any significant changes in the floor price of an NFT collection throughout the duration of the auction.

We have a strong sense for maximum and minimum prices for our auctions, but we need to establish the length and rates of price decay of our auction to maximize likelihood we find the best market-clearing price.

How long should our Dutch Auction Run?

With minimum and maximum multiples set we can in turn calculate exponential price decay λ\lambda and linear price increment ss reached across specific periods of time tt. We want to give the auction participants sufficient time to consider and be able to transact at each individual price, and in order to do so we’ll use a time increment of 15 minutes for each increment of tt. Given that these calculations will be done on-chain we will in turn translate this into certain block numbers.

With an average Ethereum block time of 12 seconds, each increment of 15 minutes represents approximately 75 blocks per tt. Or in short, every price decline will happen after 75 blocks.

But how many 15-minute intervals should we support? We dive back into real transaction data to set our benchmarks. Let’s look at how many transactions these top collections have seen in recent history. Once again we look at the past 90 days such that we accurately adapt to recent market conditions.

Total SalesHours Per SaleFirst SaleLast SaleTotal Hours

BAYC

1,177

1.8144

5/12/22 20:10

8/9/22 19:45

2,135.58

CryptoPunks

1,219

1.7402

5/13/22 10:15

8/9/22 19:36

2,121.35

Otherdeed

20,928

0.1099

5/12/22 19:15

8/16/22 14:20

2,299.07

Azuki

2,531

0.8453

5/12/22 19:15

8/9/22 22:50

2,139.58

Doodles

1,813

1.1871

5/12/22 19:19

8/10/22 11:26

2,152.13

MAYC

1,969

1.0927

5/12/22 19:37

8/10/22 11:08

2,151.52

Clone X

1,592

1.3545

5/12/22 19:24

8/10/22 15:43

2,156.31

Moonbirds

1,636

1.3201

5/12/22 19:37

8/10/22 19:14

2,159.62

In total we see these major NFT collections sell approximately once per 1-2 hours in the past 90 days. This gives us an approximate baseline for how quickly an NFT might sell in the context of an auction. A major caveat is of course that the above includes sales across OpenSea, LooksRare, x2y2, Larva Labs (for CryptoPunks), and other marketplaces.

We will make the conservative assumption that it will take a minimum of 10 to 15 times as long for the same tokens to sell within our auction, giving us a target auction time of 10-15x the NFT collection’s “Hours per Sale”. Notably this leaves the 100,000-NFT Otherdeed collection at a very low “Hours per Sale”. And as such we’ll set a duration minimum of 8 hours for our Dutch auctions.

We will target a roughly even split for our Dutch auction between Exponential decay and Linear decay. And since this will be an on-chain auction we will calculate our 15-minute increments in terms of Ethereum blocks by the approximate average block time of 12 seconds.

NFT CollectionHours Per SaleAuction Length (Hours)15min Increments (i)Ethereum Blocks

Azuki

0.85

12.68

51

3261

BAYC

1.81

18.14

73

4666

CryptoPunks

1.74

17.40

70

4475

Otherdeed

0.11

8.00

32

2057

Doodles

1.19

17.81

72

4579

MAYC

1.09

16.39

66

4215

Clone X

1.35

13.54

55

3483

Moonbirds

1.32

13.20

53

3394

Blended Decay Dutch Auction with Liquidation Penalty

One final piece of the puzzle remains—setting a reserve such that we help protect lenders and the protocol in the case of failed auctions. Here we introduce a borrower’s penalty on the final sale price of the auction which in turn goes to the Para Space protocol’s reserve.

The proceeds of the auction would thus first go to the protocol to pay off the outstanding debt dd. If the final purchase price ppurchasep_{purchase} as defined by mpurchasefloorm_{purchase} \cdot floor covers the full debt, the protocol will subtract the liquidation penalty lplp which then goes to the protocol safety reserve. Any excess would in turn go to the borrower.

With (ppurchase>d):Final Proceeds=ppurchase(1lp)d\begin{align} With \ (p_{purchase}>d): Final \ Proceeds = p_{purchase}(1 - lp) - d &&&&\end{align} \nonumber

We do this such that if ppurchasep_{purchase} is below the outstanding debt, the protocol can cover the loan with the combination of the auction proceeds and its safety reserve in order to protect liquidity providers.

The liquidation penalty (lplp) will be set on a per-NFT collection basis to help account for different levels of liquidation risks by collection with a starting value of 5% across the board.

With all of the necessary parameters in place we can now establish models for each of our supported auctions. And indeed we can easily use the same methodology to expand coverage to new NFT collections as conditions warrant.

Canceling NFT Liquidation if User’s Health Factor Recovers

As a protocol we want to support borrowers to the best of our ability, and fundamentally we would like to reward those borrowers who—after liquidation is triggered—bring their account Health Factor (HFHF) back above what we will call the recovery Health Factor: HFrecoveryHF_{recovery}.

A liquidation begins when the borrower’s HFHF falls below 1 as defined in our documentation .

HF=Collateral in ETHLiquidation ThresholdBorrows in ETH\begin{align} HF = \frac{\sum{Collateral \ in \ ETH \cdot Liquidation \ Threshold}}{\sum{Borrows \ in \ ETH}} &&&&\end{align}\nonumber

A user can always keep their HFHF above 1 by repaying some of their Borrows and/or simply add more Collateral to their account and thus keep their account from liquidation. Of course we recognize there may be instances in which a borrower may only have the means to top up their account after liquidation has already begun.

In these instances we will allow the borrower to free their NFT assets from liquidation if they bring their HFHF back above HFrecoveryHF_{recovery} which will be set to 1.1. In the future protocol governance may revisit this threshold if deemed inappropriate, but this will add further protection to the borrower who successfully returns their account to a higher HFHF.

View the full flow of the auction below as well as the FAQ’s and Appendix thereafter.

Full Dutch Auction Parameters by Supported NFT Collection

NFT Collectionm_0m_minm_minexplambdas15min increments (i)Auction Length (Hours)Ethereum BlocksLiquidation Penalty

Azuki

300%

70%

120%

0.036

0.020

51

12.68

13,114

5%

BAYC

250%

80%

120%

0.147

0.080

10

18.14

2,571

5%

CryptoPunks

500%

80%

120%

0.041

0.011

70

17.40

18,000

5%

Otherdeed

1100%

80%

190%

0.110

0.069

32

8.00

8,229

5%

Doodles

350%

70%

120%

0.030

0.014

72

17.81

18,514

5%

MAYC

200%

80%

120%

0.015

0.012

66

16.39

16,971

5%

Clone X

300%

80%

150%

0.025

0.025

55

13.54

14,143

5%

Moonbirds

200%

80%

110%

0.023

0.011

53

13.20

13,629

5%

Frequently Asked Questions - FAQ’s

What happens when there is no Successful Buy at Minimum Price?

If there is no successful purchase at pminp_{min} and the auction has failed, the protocol will seek to cover any shortfall in outstanding loan balances from its safety reserve. One protection against a failed auction is the fact that pminp_{min} is a multiple of the NFT collection floorfloor price as reported by our TWAP oracle. This should act as a way to move pp lower on any sharp declines in floorfloor.

Through governance, the Parallel protocol may use its reserve fund to purchase the NFT at the pminp_{min} and subsequently sell the NFT for the best available bid across top NFT marketplaces. If no such bid exists it will list the NFT at the prevailing market price across the same marketplaces.

Any funds recovered would replenish the amount spent out of the safety reserve and thus help protect the protocol in the face of any shortfalls. Though we of course hope this will not prove necessary, Parallel the company and/or its team may use their own funds to purchase the NFT and perform the same functions as above.

Can I buy an NFT at Auction if the User Returns their Account to the Recovery Health Factor?

No. Any outstanding auctions will become inactive if the borrower brings their account above HFrecoveryHF_{recovery}, and the Parallel website will reflect as much. Further any of the borrower’s NFT’s available for auction will be removed from the list.

The Parallel website will show the status of the auction, and the smart contract itself will confirm the user’s HFHF remains below HFrecoveryHF_{recovery} before selling the NFT at the Dutch Auction price.

Appendix - Charts

Azuki

m0=3; mmin=0.7m_0 = 3; \ m_{min} = 0.7

Bored Ape Yacht Club

m0=2.5; mmin=0.8m_0 = 2.5 ; \ m_{min} = 0.8

Mutant Ape Yacht Club

m0=2.0; mmin=0.8m_0 = 2.0 ; \ m_{min} = 0.8

CryptoPunks

m0=5; mmin=0.8m_0 = 5 ; \ m_{min} = 0.8

Otherdeed for Otherside

Otherdeeds for Otherside have a bimodal distribution — approximately 10% of tokens sell significantly above floor price. As such this will be a wider range than with other collections

m0=11; mmin=0.8m_0 = 11 ; \ m_{min} = 0.8

Doodles

m0=3.5; mmin=0.7m_0 = 3.5; \ m_{min} = 0.7

Clone X

m0=3; mmin=0.8m0 = 3 ; \ m_{min} = 0.8

Moonbirds

m0=2; mmin=0.8m_0 = 2 ; \ m_{min} = 0.8

Last updated