Yield
- 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
- 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
- for existing
- This yield is minted at a fixed rate
dETH location | dETH yield | token yield |
---|---|---|
outside system (withdrawn) | no | no |
inside system (escrowed) | no | no |
on orderbook (limit order) | no | yes (after time period) |
matched (shortRecord) | yes | yes |
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 location | shortRecord yield capture |
---|---|
outside system (withdrawn) | x% |
inside system (escrowed) | x% |
on orderbook (limit order) | x% |
collateral from shorter | 100% |
collateral from bidder | 100% |
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 thanYIELD_DELAY_SECONDS
ago.- Upon creation,
shortRecord
starts accruing yield, but it's only eligible to claim after waitingYIELD_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 ashortRecord
immediately before callingupdateYield()
can give a shorter access to a disproportionate amount of dETH yield that was generated before theshortRecord
even existed.
- Upon creation,
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.
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.
Note: Updating
dethYieldRate
is a discrete process initiated by callingupdateYield()
.dethYieldRate
must increase by at least 1 wei for a successful call. Note: Receiving yield depends on the user callingdistributeYield(assets[])
for assets in which they have createdshortRecords
. Relying on user initiated calls avoids the gas-intensive method of tracking allshortRecords
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
andbidOrder
. ExcludesaskOrder
. - 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.
- A partially filled
- The parameter
creationTime
is tracked inOrder
to determine if it's past the minimum duration required to be rewarded. This protects against two types of exploitative behavior:- 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. - Users arbitrarily creating and matching market orders and the use of flash loans to get rewards.
- Users borrowing large sums to place limit orders solely to get rewards. When
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.
- Users generate userShares (
dittoMatchedShares
) denominated in ETH-seconds, by the product of theOrder
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.
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.
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 holdingshortRecords
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 frominitialCR
. - 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.
- 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
dittoYieldSharesTotal is recorded in
Vault.dethCollateralReward
as the total dETH reward that has been claimed over the life of theVault
.dittoRewardShortersTotal
accrual is also simpler than the above method because protocol time is used instead of elapsed time, multiplied byVault.dittoShorterRate
. This simpler method can be implemented since dETH yield inherently rewards earlier owners ofshortRecords
by the use ofdethYieldRate
.
Functions
Per Vault:
updateYield(vault)
checks if the underlying LST ETH has increased in value, and if so it will update the globalVault.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'sshortRecords
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.
- dETH yield is added to a user's
withdrawDittoReward(vault)
will mint the system token to a user's wallet.
Other:
disburseCollateral
is an internal function that is called whenever collateral "leaves" ashortRecord
. This is similar todistributeYield
but pertains to a particularshortRecord
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 theshortRecord
owner.