Limbo Dev Update 2

Building Defi’s first sustainable, community configured farming dapp

Justin Goro
Behodler Liquidity Engine

--

A big thank you to Florian Pieper for being the mathematical genius we need.

Introduction

The primary purpose of Limbo will be to provide a way to liquidity mine new token listings onto Behodler. On a traditional token-pair AMM there is no minimum requirement for initial liquidity addition but the tokens must be added in correct proportions if the creator of the pair doesn’t wish to see a large and immediate impermanent loss. For instance, if the price of Eth is 2000 Dai then the pair should be seeded in that proportion. Any other proportion will see the seeder lose value to opportunistic traders who arbitrage trade the reserves into their correct levels.

Behodler also requires that tokens are seeded in correct proportions. However, unlike a token pair which is created from scratch with zero liquidity, a listing of a new token on Behodler occurs in the presence of preexisting liquidity. For instance, if we use the Eth/DAI price above, suppose Behodler has 3 Eth in reserve and we wish to list USDT. The price of Eth implies that we should list 6000 USDT in order to avoid losing value to a form of opportunistic trading known as an early bird attack. As the value of locked liquidity on Behodler grows, it becomes increasingly rare that an individual listing a new token on Behodler has enough personal capital to meet the liquidity requirement which is why we need a mining mechanism to provide incentives for many users to assist in reaching the listing threshold.

Limbo provides this mechanism by issuing a reward token (Flan) to stakers of a list of governance approved tokens. When the threshold equilibrium level is reached, the staked tokens are migrated. This raises the question of how late stakers are rewarded. To be specific, the staker who pushes the pool over the threshold will receive zero Flan staking rewards and so has no incentive to provide this final push of liquidity. If no other incentives come into play, we’ll have situation where no pool will ever reach its threshold. This article will outline the various incentives Limbo puts in place to ensure we overcome the threshold conundrum by explaining the fundamental mechanics.

Flash Governance

The parameters outlined in this article will all be configurable. The incentives to boost the value of Flan and to increase the scope of Behodler are all aligned to the extent that the entire community has an aggregate incentive to make Limbo successful. When the incentives of a disparate mob are aligned, it becomes a hive. A focused hive mind is far more agile and effective than any individual and so for this reason, Limbo will be rolled out as a community run, decentralised yield farm.

In order to achieve this, we need a reliable mechanism for governance. The previous update explained how voting points (Fate), earned through staking EYE or EYE LP, can be used to lodge proposals or cast votes.

There can only be one active proposal at any point to prevent an attacker slipping through malicious governance through a DOS submission of proposals (a Karen attack?). Each proposal can take a fairly long time to clear as all users need at least 24 hours to consider them due to time zones. It’s not certain at this point how many pools Limbo will run but if there is more than one pool running concurrently and some parameters need adjusting, the traditional proposal mechanism may become a bottleneck. In particular there are some parameters such as the proportion of Flan rewarded to a given pool that do not pose a systemic risk to the Behodler.

For this reason there is an additional layer of fast governance introduced called Flash Governance. Here, an asset is chosen by the community such as EYE. Any of holder of EYE can then stake their EYE and immediately execute a certain subset of governance decision related to calibration without voting approval. There are some caveats:

  1. The stake is locked for a fairly long duration. The community can then take its time reviewing if the flash governance decision was either malicious or undesired and submit a regular fate based proposal to burn the deposit.
  2. The parameters open to flash governance calibration have a certain maximum percentage change per time period to protect against massive disruptions and to prevent flash governance from being used as a flash loan attack vector.
  3. The number of flash governance decisions in a given period of time, known as an epoch, is also limited to prevent a Karen attack.

In addition to agility, the Flash Governance mechanism also allows the community to replicate traditional proposals at the lowest possible gas cost. Here, anyone can list a proposal on Snapshot and request votes. When the votes are in, one person can stake EYE and execute the decision. This saves voters from spending any gas. If the governance executor goes rogue, we then have the backstop layer of Fate governance proposals to call on in order to burn their stake. So Flash Governance can also be seen as a kind of Layer 2 governance for Limbo.

Two types of pools

Limbo’s main form of pool will be threshold based. Here, a goal of TVL is set and when the goal is reached, the pool locks. At this point the tokens can be migrated to Behodler, generating Scarcity which is then used to purchase and pool Flan.

In addition, there are traditional ‘perpetual’ pools which have no end point. These pools can be used for systemic incentives. For instance, holders of SCX, Flan, EYE or any LP combination of those could be staked for ongoing Flan rewards to encourage perpetual lockup. Since the value of SCX determines the ongoing value of Flan, providing Flan rewards for locking up SCX is offset by the deflationary pressure applied to SCX from the lockup and hence Flan.

Incentives for Threshold pools

To reiterate the threshold conundrum, the final person to stake in a threshold pool receives none of the flan emissions awarded during the staking period. For this reason there needs to be an incentive to cross the finish line. There have been a number of suggestions such as paying staking rewards for a certain period after the threshold is passed or figuring out who’s making a loss and making them whole but they all suffer from requiring a price oracle to provide an exchange rate between Flan and the token being staked. This oracle can’t be a simple quote from an AMM since flash loan pirates are roaming the seas with aggression as most of the recent exploits have shown. To introduce a more sophisticated oracle system adds a great layer of complexity and does nothing to prevent MEV front running style attacks.

It would be preferable to have a simple mechanism that can’t be gamed and for which the community itself acts as an oracle, since the community’s net incentive is for the welfare of Limbo and Behodler. To this end, Limbo will have two levers of incentives: a crossing bonus and a crossing bonus delta. Simply put, a pool will pay a price in Flan per token when the threshold is crossed. For instance, suppose we’re listing Sushi and I stake 120 Sushi. The crossing bonus for the pool is set at 1.5 Flan per Sushi. When the pool threshold is finally reached, I receive (1.5x120=) 180 Flan in addition to whatever I received through staking. The community can then adjust the crossing bonus to carefully reflect the exchange rate so that we don’t issue too much Flan or not enough. In reality we can probably pay the final threshold staker less than the market rate for Flan because the final staker is likely to be an existing staker and is wishing to nudge the pool over the threshold in order to effect an SCX boost to the Flan value.

In addition to this bonus, each pool has a delta. This is how much the bonus is adjusted per second during the staking phase. This number can be negative or positive. If it’s negative, we have a traditional Dutch Auction where the crossing bonus starts off high and gradually declines. Here the community has maximum incentive to cross the threshold as fast as possible in order to get the highest possible bonus. For example we start with a crossing bonus of 3 Flan per input token and a delta of -0.001 Flan per second. After the first 20 seconds, the crossing bonus has declined to (3–0.02=)2.98 Flan per token.

Negative crossing delta (left) vs positive crossing delta (right). Ti represents the market price of Flan.

When the crossing bonus delta is positive, it means the crossing bonus starts off low and rises per second. The incentive here is to gradually nudge marginal holders of the staking token into joining the farm in order to get an increasing reward. Eventually the incentive will be high enough to push the pool over the threshold. As you can see, one parameter can radically change the market dynamic and provides a great way for the community to experiment with the best way to bring new holders to Limbo in the most cost effective manner. The crossing bonus and the crossing bonus delta are both open to Flash Governance so that as market conditions change, the rewards can be updated quickly.

Threshold attack vector closed: Just in time Oracle

When the threshold is crossed, anyone can execute the migration function. Here the tokens staked are injected into Behodler and SCX is generated. A portion of the SCX generated is burnt (more on that below) and the rest is used to buy Flan and then pool that Flan in an LP on either Uniswap or Sushiswap. This operation requires we know the market price of Flan. While the spate of recent flash loan exploits has revealed that relying on AMM spot price quotes is very dangerous, all is not lost. The solution is fairly simple and doesn’t require an oracle. The key point in all flash loan exploits and indeed the definition of a flash loan is that the manipulation and profit taking have to happen in the scope of a single transaction. A simple fix is to require the pricing and migration happen in separate blocks. In particular, we have one block where the reserves of Flan and SCX in the Flan/SCX LP are recorded. In a later block (community specifies the minimum duration of blocks between these events) the migration takes place. Here the reserve levels of SCX and Flan are read again and compared to the previous recording. If the levels have diverged too much, the transaction fails. This immediately protects against flash loan attacks since any spike manipulation causes a revert. What about an aggressive whale (Orca?) who can raise the price in the first instance with sheer market power and then act on that in the migration block? This is the purpose of requiring a certain period of time has passed between the first recording and the migration. The duration between the recordings is where profit seeking market participants can return the price to equilibrium. The cost for a killer whale to keep the price out of whack for multiple blocks multiplies with each successive block. Of course, insert too many blocks and the price will have enough time to drift naturally which may lead to a false positive revert. Here again, the community will need to experiment with the optimal parameters.

As a final backstop, there’s a lock-all governance trigger that can disable the Limbo protocol in the case of an emergency such as an attack on the Flan price.

Side note: the migration is quite gas intensive. Whoever invokes migrate will receive a Flan reward for their troubles.

How much Scarcity should we burn? Introducing the Rectangle of Fairness

Logarithmic bonding curves are the most effective way to price any level of liquidity without requiring liquidity concentration or swap curve manipulation. The mathematics of logarithmic bonding curves implies that the marginal price of a given pair of tokens is the ratio of their liquidity. This scales to any level. In other words, since 10/100 is equal to 10000000/100000000, the price mechanism doesn’t break down at low or high levels of liquidity so long as the ratios are still correct. Any other formula (quadratic, linear, xlogx etc.) may work at certain levels but doesn’t scale. Quadratic is great for tokens of the same type such as stable coins. xlogx handles very low levels of liquidity well but falls apart at high levels and linear provides undefined pricing.

Unlike AMMs which mint liquidity tokens simply as shares of liquidity, Scarcity is also the medium of exchange on Behodler and so is minted along the bonding curve. One of the quirks of a single sided bonding curve is that very low levels of liquidity produce far more Scarcity than higher levels. This has been covered elsewhere but essentially, the first person to add just a single unit of liquidity to Behodler is rewarded with 366 SCX. If we take an SCX price of just $200 then the initial kick of 1 unit will yield $73200 of Scarcity. That’s almost double the price of Bitcoin. Imagine if we list a dollar stable coin and the first person to add liquidity spends $1 in order to receive $73200 of SCX. this is clearly not sustainable or fair. The introduction of Flan ensures that there is no first receiver but rather that the entire quantum of SCX produced is spread as demand pressure over the Flan market. However, there is still an excess of SCX produced and using it all to purchase Flan will inflate the supply of SCX beyond its current value. Consider the graph below.

SCX bonding curve in terms of token, T

The line B represents a bonding curve on Behodler. Each point on the line is the total amount of SCX minted for the given level of tokens, T. SCXe is the equilibrium level of SCX minted for Te tokens.

Observant readers will notice the curve cuts the origin which can’t happen for a logarithmic curve. Bear in mind that Behodler, like other AMMs, has a minimum level of liquidity so this detail is not relevant. Indicating such detail on the graph adds no visual value.

Suppose we take the price of SCX at Te which is just SCXe/Te. Since this is the market price, a fair distribution of SCX would be such that everyone supplying T up until Te receives this price. Since T increases linearly but SCX increases logarithmically, it follows that SCX/T is declining for increasing levels of T. In other words, early adopters receive a disproportionate share of SCX. While this creates useful incentives in bringing new users to Behodler, the excess SCX given to those buying below market price inflates the supply of SCX and undermines its value. In the case of a Limbo migration, we don’t wish to reward early adopters since the SCX is spread in one purchase over the entire Flan market. So we’d like to burn this excess SCX. In order to understand how to calculate the excess SCX minted, we need to consider the graph of the marginal price of SCX which is just the first derivative of the bonding curve formula. In this case, the first derivative with respect to t for a logarithmic bonding curve is 1/t. Consider the following graph:

Marginal Scarcity price of T, represented by SCX’

The curve represents the first derivative of the bonding curve which is 1/t. If we wish to calculate the total SCX minted, we take the definite integral from 1 to Te, represented by the area A+B.

Note that at Te, the point on the vertical axis is the marginal SCX price of Te. This is the price we want everyone to receive, not just the latest purchaser. Since we wish to distribute this price of Te to all contributors for fairness sake, we can just multiply this value by Te. This gives us the rectangle A. We can term the rectangle A, the Rectangle of Fairness since it presents the quantum of SCX that on its own, neither inflates not deflates the value of SCX. This means that the area marked by B is excess SCX that needs to be burnt. All that is required is to calculate A.

Inferring Excess Scarcity

In Limbo, the value of Te at migration can be taken as given since this is just the threshold set by governance. The value of A+B is simply the quantity of SCX produced from the migration event. The Behodler contract provides a function called withdrawLiquidityFindSCX which calculates the amount of T required to produce a given input of SCX, given the current level of reserves. Using this function, we an calculate A by passing in a very small value for SCX. Let’s call this value S. We then take the token value returned from withdrawLiquidityFindSCX and divide it S to get a close approximation of SCXe′. Multiplying this by Te gives us A. To find B, we simply subtract A from total SCX minted. In notation,

Since SCX = A+B
=> B = SCX - A

This means that without any oracle, we can calculate the quantum of SCX to burn in the same transaction in which the migration occurs.

The code for this has been written and automated testing has been prepared and is in the process of being written.

For next time

It was initially suspected that when first released, Flan won’t have a market value and will only acquire one after the first listing. In other words, the very first stakers will be acting on faith. Since then, a mechanism for giving Flan instant liquidity and market value has been discovered. This event will be known as Flan’s Genesis Event and will be explained in further detail in the next dev update.

--

--