Skip to content

Yield

  1. dETH yield is staked ETH rewards.
    • This yield comes from yield gained from LST ETH in the system
    • This yield is distributed to existing shortRecords
  2. Token yield is the system's token, given as additional rewards.
    • This yield is minted at a fixed rate
      • for existing shortRecords
      • for providing liquidity on the OrderBook
dETH locationdETH yieldtoken yield
outside system (withdrawn)nono
inside system (escrowed)nono
on orderbook (limit order)noyes (after time period)
matched (shortRecord)yesyes

dETH Yield

The system is denominated in dETH. Any deposited ETH tokens (ETH, rETH, stETH) are converted into dETH.

dETH is only a stablecoin for ETH. It does not gain any yield on its own or by holding it. Instead, all dETH yield - generated by the underlying LST - is given to matched shorters in the system (ie. in a shortRecord position). Any dETH that is not matched has no claim to yield generated by the system and cedes yield to matched shorters. This includes dETH outside the system, inside the system, and on the orderbook. Hence, yield for matched shorters becomes supercharged as they are eligible for yield beyond just their provided collateral.

dETH locationshortRecord yield capture
outside system (withdrawn)x%
inside system (escrowed)x%
on orderbook (limit order)x%
collateral from shorter100%
collateral from bidder100%

For example with initialCR = 2, a shorter would be guaranteed at least 50% (1 ETH from bidder/ 2 ETH from shorter) yield beyond simply holding the equivalent ETH value of LST. In practice, this figure would be higher as the shorter also receives x% (where x > 0) of the yield generated from dETH from non-matched positions. This percentage is determined proportionally by the collateral in a shortRecord compared to the collateral in all shortRecords.

Eligibility Criteria:

  • Only applies to shortRecord.
  • shortRecord created/modified more than YIELD_DELAY_SECONDS ago.
    • Upon creation, shortRecord starts accruing yield, but it's only eligible to claim after waiting YIELD_DELAY_SECONDS.
    • This protects against flash loans where a user could open massive short positions to artificially harvest yield. Since LST are continuously generating yield, lagtime exists between LST yield and when it's recorded in the system due to the discrete (but cheaper) manner of calling updateYield(). Therefore, matching a shortRecord immediately before calling updateYield() can give a shorter access to a disproportionate amount of dETH yield that was generated before the shortRecord even existed.

Accrual Mechanism:

Similar to Uniswap's concept of feeGrowth, dETH yield is tracked by a monotonically increasing global rate. dethYieldRate is defined as the yield earned per unit of collateralized dETH over all shortRecords in the same Vault, since only dETH collateralized in a shortRecord is eligible to earn yield.

dethYieldRate=dethYieldRate+yielddethCollateral

Upon creation, each shortRecord reads the current dethYieldRate and saves it as a parameter. When yield is distributed, the updated dethYieldRate is compared against the last saved dethYieldRate and the difference - the yield differential per unit of dETH collateralized - is multiplied by the amount of dethCollateral in a given shortRecord to determine the amount of dETH yield. The new updated dethYieldRate is then written to the shortRecord to eliminate double counting of yield.

yield=(Vault.dethYieldRateshort.dethYieldRate)short.dethCollateral

Note: Updating dethYieldRate is a discrete process initiated by calling updateYield(). dethYieldRate must increase by at least 1 wei for a successful call. Note: Receiving yield depends on the user calling distributeYield(assets[]) for assets in which they have created shortRecords. Relying on user initiated calls avoids the gas-intensive method of tracking all shortRecords and looping through them.

TAPP

The Treasury Asset Protection Pool (TAPP) stores the treasury's percentage of yield via dethTithePercent as a system fee, and can be used to cover bad debt

Token Yield

From Matching

To bootstrap and incentivize liquidity on the OrderBook, rewards are provided for matched limit orders that have been sitting on the OrderBook over a certain time period, akin to how an AMM like Uniswap may reward liquity providers (LPs).

Eligibility Criteria:

  • Only applies to shortOrder and bidOrder. Excludes askOrder.
  • If an Order is cancelled, the user will lose their rewards because rewards are earned only upon successfully matching.
    • A partially filled Order can generate rewards proportional to the amount filled.
  • The parameter creationTime is tracked in Order to determine if it's past the minimum duration required to be rewarded. This protects against two types of exploitative behavior:
    1. Users borrowing large sums to place limit orders solely to get rewards. When creationTime is appropriately determined, these users will have to weigh the cost of borrowing against potential rewards.
    2. Users arbitrarily creating and matching market orders and the use of flash loans to get rewards.

Accrual Mechanism:

User rewards are determined proportionally by the number of user shares in comparison to the total shares by Vault. The total number of shares in the Vault (totalShares) and the total amount of reward available to claim (totalReward) are dynamic values. Thus, the amount of reward claimed by a user is not static and is dependent on the Vault conditions at the time of claim.

userReward=totalRewarduserSharestotalShares

  • Users generate userShares (dittoMatchedShares) denominated in ETH-seconds, by the product of the Order amount (in ETH) and time until match (in seconds).
  • Upon claiming token reward the entire balance of userShares is "used" and the balance is zeroed out.
  • totalShares increases and decreases as users gain and redeem shares.

The totalReward (dittoMatchedReward) is updated by user claims according to the per second rate dittoMatchedRate and the elapsed time since the last call of claimDittoMatchedReward. While the amount of totalReward is dynamic, the accrual occurs at a fixed rate meaning a fixed amount of token minting over time.

dittoMatchedReward=elapsedTimedittoMatchedRate

From Shorts

Holders of shortRecords also receive token rewards in addition to dETH yield in order to further incentivize holding short positions. However, instead of developing another separate system of shares, these token rewards simply scale with the amount of dETH yield that a user has claimed. This simpler mechanism saves gas without introducing new state variables and is also not static like the above method.

dittoReward=dittoRewardShortersTotaldittoYieldSharesdittoYieldSharesTotal

  • dittoYieldShares is the immediate amount of dETH yield being distributed to a user during a call of distributeYield(assets[]) that is modified by a reduction factor inversely proportional to CR (initialCR/CR) that is capped at 100%.

    • The proportional reduction is designed to incentivize users to utilize excess capital efficiently and for the creation of new debt, while discouraging the creation of shortRecords with high CR that are over-stuffed with collateral. This disincentive model exists alongside the inherent lower capital efficiently of holding shortRecords with high CR.
    • This reduction for higher CR discourages reward farming by eliminating ditto tokens earned by all collateral beyond what would be needed to maintain a shortRecord at the CR derived from initialCR.
    • Since decreaseCollateral() does not credit users with ditto tokens there is no benefit to decreasing collateral immediately before a yield distribution in order to lower a short position CR.
  • dittoYieldSharesTotal is recorded in Vault.dethCollateralReward as the total dETH reward that has been claimed over the life of the Vault.

  • dittoRewardShortersTotal accrual is also simpler than the above method because protocol time is used instead of elapsed time, multiplied by Vault.dittoShorterRate. This simpler method can be implemented since dETH yield inherently rewards earlier owners of shortRecords by the use of dethYieldRate.

dittoRewardShortersTotal=protocolTimedittoShorterRate

Functions

Per Vault:

  • updateYield(vault) checks if the underlying LST ETH has increased in value, and if so it will update the global Vault.dethYieldRate.
  • claimDittoMatchedReward(vault) will distribute system tokens to a user from all OrderBooks for any matched orders over the minimum duration.

Per User:

  • distributeYield(assets[]) will loop over a list of assets and loop through a user's shortRecords to increase both a user's dETH yield and token yield.
    • dETH yield is added to a user's ethEscrowed so they can withdraw as normal.
  • withdrawDittoReward(vault) will mint the system token to a user's wallet.

Other:

  • disburseCollateral is an internal function that is called whenever collateral "leaves" a shortRecord. This is similar to distributeYield but pertains to a particular shortRecord and distributes yield only for the amount of collateral that is being decreased. This way unrealized yield that was not distributed is captured before permanent loss. YIELD_DELAY_SECONDS is also utilized here to prevent flash loan exploits that quickly make shorts and exit them. When this time condition is not satisfied, the distributed yield is sent to the TAPP instead of the shortRecord owner.