Author: Markus Laeng @m.laeng (Forum) & Florin Avram @florin (Forum), youves contributors
Related discussions & posts: Strategic Vision for youves
First publication date: 2023/07/04
Note:
This post is the final version and unless there is reason to do so, it will not be edited anymore. All edits are listed at the end of the post. Once YIP-01 is live on the governance post of youves, please compare it to this post. Submitted text, code, code hash and smart contracts should be identical.
Summary
As laid out in the Strategic Vision for youves, we are convinced that we need to improve the platform for more capital efficiency in order to grow. One proposed initiative is to transform the current role of the saver into the role of a liquidity provider. We want to test this transformation with the uXTZ Savings Pool. The proposed path of actions would be to:
- develop and deploy a new uXTZ/XTZ flat curve pool, with the DAO contract as admin.
- set this new flat curve pool as the sole recipient of all the interest rate payments that are paid on all uXTZ engines. The uXTZ savings pool will not get anymore rewards.
- remove the timelock on the current uXTZ savings pool, so uXTZ savers can remove their saved uXTZ with full rewards immediately.
- remove the timelock on the uXTZ/XTZ farm, so users can remove their LP tokens with full rewards immediately.
Further, after observing voter participation during YIP-0, we think that we could shorten the voting period on YIPs by around 2 days, reducing it from roughly 7 days to two five days. We think this should be enough for all YOU stakers to send their votes. So another proposal of this YIP-1 is to:
- reduce the Voting period on the DAO contract to 28’800 blocks (roughly 5 days), instead of currently 40’320 (roughly 7 days).
Rationale
In our Strategic Vision for youves, we identified the synthetic assets locked in Savings Pools as unused capital, because once locked, this capital can not be used by other platform participants. But in order to empower trading on youves, it is in the platforms interest to have as much liquidity available as possible. Without sufficiently large liquidity pools, minters face difficulties in swapping their minted synthetic assets for the desired position or even in repaying their loans.
In order to turn savers into liquidity providers, we think it is a careful approach to test this with the uXTZ savings pool and the uXTZ/XTZ flat curve pool.
Motivation
In order to use the capital locked in the uXTZ savings pool, a new flat curve pool with new properties was developed and deployed. With this YIP, the incentives will be set for users to move their funds from the uXTZ savings pool into the new flat curve pool.
The new youves yield uXTZ/XTZ flat curve pool
New feature: reward accrual
The new youves yield uXTZ/XTZ pool is a flat curve pool with the same constant function as all other youves flat curve pools. But it comes with new properties: The interest rate payments of all uXTZ engines accrue in this pool, the baking rewards of the XTZ that is locked in the liquidity pool and 50% of the trading fees (as before) of the pool itself. This constant flow of rewards into the pool, results in a increasing value of the liquidity tokens over time. The pool keeps track of the current value, by recalculating the price of the liquidity token at target value (1 uXTZ : 1 XTZ) whenever interest rate payments or baking fees are sent to the pool.
An example: If the pool is holding 10 XTZ and 10 uXTZ and issued 10 liquidity tokens, value of a liquidity token will be 10xtz + 10xtz (in this case we assumed 1 uxtz = 1 xtz) / 10 = 2 xtz. So the value of the liquidity token is: (total_amount_of_token_a + total_amount_of_token_b * target_price_of_token_b_in_token_a) / total_amount_of_lqt_tokens.
If now a reward (interest rate payment or baking reward) of 5 XTZ is sent to the pool, and the pool then holds 10 uXTZ and 15 XTZ with 10 liquidity tokens issued, then the price of 1 liquidity token will be 2.5 XTZ.
If we assume a user had deposited liquidity worth 2 XTZ before the reward was received by the pool, then he could exit the pool with liquidity worth 2.5 XTZ.
yyXTZ - the new liquidity token
The liquidity tokens minted by this new youves yield flat curve pool will be named yyXTZ (for youves yield XTZ) in order to indicate that this liquidity token is capturing the yield of the synthetic asset engine. yyXTZ is FA 1.2 compliant, following the TZIP-7 standard. It has 12 decimals.
Liquidity token contract: KT1NtfNBPAo8UrcMexMyrKR5WCHb3VRiocvx
See token metadata here: See token metadata here: https://ipfs.io/ipfs/QmeH4ZajL6ZLWeEk3xmidiJUqKYsjN1CQRmR7bgeFsnu8K
Note:
The deployment of the new flat curve pool itself is not part of this vote. It has already been deployed by us, with the DAO contract as the initial administrator, see information about ghostnet and mainnet instances below. The lambda of this YIP, will set this new pool as the recipient of the interest rate from all uXTZ engines.
Security Audit
The contract of the new youves yield uXTZ/XTZ pool has been audited by inference AG. See audit report in the GitHub of inference here:
GitHub - InferenceAG/ReportPublications (will be published as soon as the final version is available)
Source code
The code of the new pool is published and can be reviewed here:
Final ghostnet instance
Ghostnet instance of the final contract:
KT1Vc1jG85EHH9SLqWCpH2DdtTtnCnCHor55
View ghostnet contract on better-call.dev
Final mainnet instance
Mainnet instance of the final contract:
KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS
View mainnet contract on better-call.dev
The mainnet instance is fully functional at this point, but we recommend not to use it until the YIP passed. Only after the YIP, the rewards will be sent to it.
Savers will move their funds into the new youves yield uXTZ/XTZ flat curve pool
Once the uXTZ Savings Pool is unlocked and does not receive any more rewards, the current savers will remove their funds given the lack of incentives to keep the uXTZ in the Savings Pool. If they are interested to continue earning yield from the interest rate paid by minters, they will have to move their funds into liquidity for the uXTZ/XTZ pool. This can be done by either swapping some of the uXTZ into XTZ or, if they are uXTZ minters too, by burning some of the uXTZ in order to free collateral to swap into tez for depositing into the liquidity pool.
Liquidity providers in the old uXTZ/XTZ flat curve pool and farm will move their funds into the new uXTZ/XTZ flat curve pool
In order to participate in the new uXTZ/XTZ pool, users who are currently having a position locked in the current uXTZ/XTZ farm, will want to move their liquidity tokens of uXTZ/XTZ into the new pool. This implies that we need to remove the timelock in the old uXTZ/XTZ farm, so users can remove all of their locked LP tokens and all of the rewards they are entitled to.
This proposal will remove the timelock on the old uXTZ/XTZ farm, which allows farm participants to remove their old uXTZ/XTZ liquidity tokens in order to remove their liquidity from the old uXTZ/XTZ flat curve pool.
Farm rewards for the old uXTZ/XTZ farm will be stopped upon execution of this YIP. But the declining baking rewards on the uXTZ/XTZ farm will be swapped into YOU and paid to the liquidity providers of the old uXTZ/XTZ pool as long as they accrue.
Deeper liquidity for uXTZ/XTZ
The steps above should lead to increased liquidity in the uXTZ/XTZ pool. The old pool currently has around 94k XTZ and 130k uXTZ of liquidity, so around 224k XTZ worth of liquidity. The current savings pool has around 246k uxtz locked. We expect most of it being shifted into the liquidity pool, which would more than double the liquidity the uXTZ/XTZ pair currently has. A deeper liquidity pool will allow traders to trade bigger volumes with less slippage, which allows them to enter directional trades.
Incentives for liquidity providers
If this YIP passes, liquidity providers of uXTZ/XTZ which lock their tokens in the new flat curve pool, will receive their fair share of 1) the baking rewards of the locked XTZ 2) the interest rate paid by all minters of uXTZ. Currently no further incentives for uXTZ/XTZ providers are planned.
Proposal
The following sections explain the content of the lambda that will be executed if this YIP is accepted by YOU stakers:
Change 1 - Remove timelock on the uXTZ/XTZ farm
Update the release period for the uXTZ farm:
The lambda will call the entrypoint set_max_release_period
on KT1HbzGokeEZ4hu1KRAAw2fyB61RCpBhQXKA
to set max_release_period to 1.
After this change, users can immediately remove their liquidity tokens from the uXTZ/XTZ farm, without loosing out on rewards. The parameter has to be set to 1 because 0 is not allowed to be set. 1 means a max_release_period of 1 second will be set after which a user can claim his full rewards.
Change 2 - Remove timelock on the uXTZ savings pool
Update the release period for the current uXTZ savings pool:
The lambda will call the entrypoint update_max_release_period
on KT1KShHvxW69YukaGetdgYRTw31d9BX8ijfF
to set max_release_period to 1.
After this change, users can immediately remove their uXTz from the uXTZ savings pool, without loosing out on rewards. The parameter has to be set to 1 because 0 is not allowed to be set. 1 means a max_release_period of 1 second will be set after which a user can claim his full rewards.
Change 3 - Reduce the Voting Period on the DAO contract
Update the voting period on the DAO contract:
The lambda will call the entrypoint set_governance_params
on the DAO contract KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab
to set vote_length_blocks
in the governance_params
to 28’800 blocks. All other governance_params
will be unchanged.
Change 4 - Set the new flat curve as the interest rate payments receiver
Set the new flat curve pool as the new savings_pool_contract
which is the sole recipient of all the interest rate payments that are paid on all uXTZ engines. As a consequence, the old uXTZ savings pool KT1KShHvxW69YukaGetdgYRTw31d9BX8ijfF
will not get anymore rewards:
4A
The lambda will call the entrypoint set_contracts
on the uXTZ engine with USDT collateral (KT1AnDFRcdB652Jy5JFtmu7SampSPAzDkK7g
) to set KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS
as the new savings_pool_contract
replacing the previous contract KT1KShHvxW69YukaGetdgYRTw31d9BX8ijfF
(the discontinued uXTZ savings pool). All other contracts remain unchanged.
4B
The lambda will call the entrypoint set_contracts
on the uXTZ engine with XTZ collateral (KT1Mf9Nr1KyGC6gUz9pGQnngzWbbZ6thShvc
) to set KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS
as the new savings_pool_contract
replacing the previous contract KT1KShHvxW69YukaGetdgYRTw31d9BX8ijfF
(the discontinued uXTZ savings pool). All other contracts remain unchanged.
4C
The lambda will call the entrypoint set_contracts
on the uXTZ engine with SIRS collateral (KT1ByNrcyDxYLmamuJbeFJukYkLJaZ1W86Yr
) to set KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS
as the new savings_pool_contract
replacing the previous contract KT1KShHvxW69YukaGetdgYRTw31d9BX8ijfF
(the discontinued uXTZ savings pool). All other contracts remain unchanged.
Code
Source code in SmartPy
This is the SmartPy source code of the lambda which will be executed with this proposal, YIP-1:
Also published on: https://github.com/youves-com/youves-proposals/blob/main/yip-01/yip-01-smartpy.py
def execute_set_contracts_engine_v3(
engine_address,
interest_rate_setter_contract,
options_contract,
governance_token_contract,
savings_pool_contract,
target_price_oracle,
reward_pool_contract,
):
engine_contract = sp.contract(
sp.TPair(
sp.TPair(sp.TAddress, sp.TPair(sp.TAddress, sp.TAddress)),
sp.TPair(sp.TAddress, sp.TPair(sp.TAddress, sp.TAddress)),
),
engine_address,
entry_point="set_contracts",
).open_some()
payload = sp.pair(
sp.pair(
governance_token_contract,
sp.pair(interest_rate_setter_contract, options_contract),
),
sp.pair(
reward_pool_contract, sp.pair(savings_pool_contract, target_price_oracle)
),
)
return sp.transfer_operation(payload, sp.mutez(0), engine_contract)
def DAO_YIP_01(unit):
sp.set_type(unit, sp.TUnit)
###############################################################################
# Update the release period for uXTZ/XTZ farm and uXTZ savings pool constants #
###############################################################################
farm_entrypoint = sp.contract(
sp.TNat,
sp.address('KT1HbzGokeEZ4hu1KRAAw2fyB61RCpBhQXKA'), # uXTZ/XTZ youves farm
entry_point="set_max_release_period"
).open_some(message='Farm: Invalid entry point set_max_release_period')
savings_pool_entrypoint = sp.contract(
sp.TNat,
sp.address('KT1KShHvxW69YukaGetdgYRTw31d9BX8ijfF'), # uXTZ savings pool
entry_point="update_max_release_period"
).open_some(message='Savings pool: Invalid entry point update_max_release_period')
# 1 second release period (0 is not allowed to avoid divisions by 0)
new_max_release_period = sp.nat(1)
###################################
# DAO new voting period constants #
###################################
dao_entrypoint = sp.contract(
GOVERNANCE_PARAMS_TYPE,
sp.address('KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab'), # youves DAO
entry_point="set_governance_params"
).open_some(message='DAO: Invalid entry point set_governance_params')
# new governance params for DAO
new_governance_params = sp.record(
escrow_amount = sp.nat(500_000_000_000_000), # 500 YOUs (remains the same)
vote_delay_blocks = sp.nat(11520), # 2 days (remains unchanged)
vote_length_blocks = sp.nat(28800), # from 7 days to 5 days
min_yes_votes_percentage_for_escrow_return = sp.nat(30), # 30% (remains unchanged)
timelock_execution_delay_blocks = sp.nat(11520), # 2 days (remains unchanged)
timelock_cancelation_delay_blocks = sp.nat(23040), # 4 days (remains unchanged)
super_majority_percentage = sp.nat(80), # 80% (remains unchanged)
quorum_cap = sp.record(
lower = sp.nat(800_000_000_000_000_000), # 0.8M (remains unchanged)
upper = sp.nat(3_744_000_000_000_000_000) # 3.744M (remains unchanged)
),
)
sp.set_type_expr(new_governance_params, GOVERNANCE_PARAMS_TYPE)
#######################################################
# New minting fee receiver for uXTZ engines constants #
#######################################################
new_uxtz_xtz_pool = sp.address('KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS') # Address of the new uXTZ/XTZ constant function market maker.
# DAO LAMBDA
sp.result(sp.list([
sp.transfer_operation(new_max_release_period, sp.mutez(0), farm_entrypoint),
sp.transfer_operation(new_max_release_period, sp.mutez(0), savings_pool_entrypoint),
sp.transfer_operation(new_governance_params, sp.mutez(0), dao_entrypoint),
execute_set_contracts_engine_v3(
sp.address('KT1AnDFRcdB652Jy5JFtmu7SampSPAzDkK7g'), # uXTZ/USDt collateral engine
sp.address('KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab'), # youves DAO as interest rate setter (remains the same)
sp.address('KT1BUR5mjwBWzojKRqWrng8ASBh3N3LLV7NM'), # options contract (remains the same)
sp.address('KT1Ge5usHwAAH12PDxwP8FFYMdbMbXSRXSz4'), # stake manager (remains the same)
new_uxtz_xtz_pool, # mint fee rewards receiver (previously was savings pool)
sp.address('KT1PvKziQx7pJhfr3FdvkhMPwCwLxjd32HkZ'), # target price oracle (remains the same)
sp.address('KT1KXvsh7vnPUkBj1oG1E3LUoFnKHsf7Wixo'), # unified staking proxy as rewards receiver (remains the same)
),
execute_set_contracts_engine_v3(
sp.address('KT1Mf9Nr1KyGC6gUz9pGQnngzWbbZ6thShvc'), # uXTZ/XTZ collateral engine
sp.address('KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab'), # youves DAO as interest rate setter (remains the same)
sp.address('KT1CHL9XVrt3Avr1mHkCiZBANEeJzbUSGqGB'), # options contract (remains the same)
sp.address('KT1Ge5usHwAAH12PDxwP8FFYMdbMbXSRXSz4'), # stake manager (remains the same)
new_uxtz_xtz_pool, # mint fee rewards receiver (previously was savings pool)
sp.address('KT1PuCU5UAoaX2Hjcns2SEmJWBC34tfLjzaS'), # target price oracle (remains the same)
sp.address('KT1KXvsh7vnPUkBj1oG1E3LUoFnKHsf7Wixo'), # unified staking proxy as rewards receiver (remains the same)
),
execute_set_contracts_engine_v3(
sp.address('KT1ByNrcyDxYLmamuJbeFJukYkLJaZ1W86Yr'), # uXTZ/SIRS collateral engine
sp.address('KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab'), # youves DAO as interest rate setter (remains the same)
sp.address('KT1BUR5mjwBWzojKRqWrng8ASBh3N3LLV7NM'), # options contract (remains the same)
sp.address('KT1Ge5usHwAAH12PDxwP8FFYMdbMbXSRXSz4'), # stake manager (remains the same)
new_uxtz_xtz_pool, # mint fee rewards receiver (previously was savings pool)
sp.address('KT1TSwSAU1qUyRFYBv6ix5YzqLBparxJ3FAk'), # target price oracle (remains the same)
sp.address('KT1KXvsh7vnPUkBj1oG1E3LUoFnKHsf7Wixo'), # unified staking proxy as rewards receiver (remains the same)
),
]))
Compiled Michelson code
This is the compiled Michelson code of the above SmartPy code.
Also published on: https://github.com/youves-com/youves-proposals/blob/main/yip-01/yip-01-michelson.tz
{ NIL operation; PUSH address "KT1ByNrcyDxYLmamuJbeFJukYkLJaZ1W86Yr"; CONTRACT %set_contracts (pair (pair address (pair address address)) (pair address (pair address address))); IF_NONE { PUSH int 176; FAILWITH } {}; PUSH mutez 0; PUSH (pair (pair address (pair address address)) (pair address (pair address address))) (Pair (Pair "KT1Ge5usHwAAH12PDxwP8FFYMdbMbXSRXSz4" (Pair "KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab" "KT1BUR5mjwBWzojKRqWrng8ASBh3N3LLV7NM")) (Pair "KT1KXvsh7vnPUkBj1oG1E3LUoFnKHsf7Wixo" (Pair "KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS" "KT1TSwSAU1qUyRFYBv6ix5YzqLBparxJ3FAk"))); TRANSFER_TOKENS; CONS; PUSH address "KT1Mf9Nr1KyGC6gUz9pGQnngzWbbZ6thShvc"; CONTRACT %set_contracts (pair (pair address (pair address address)) (pair address (pair address address))); IF_NONE { PUSH int 176; FAILWITH } {}; PUSH mutez 0; PUSH (pair (pair address (pair address address)) (pair address (pair address address))) (Pair (Pair "KT1Ge5usHwAAH12PDxwP8FFYMdbMbXSRXSz4" (Pair "KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab" "KT1CHL9XVrt3Avr1mHkCiZBANEeJzbUSGqGB")) (Pair "KT1KXvsh7vnPUkBj1oG1E3LUoFnKHsf7Wixo" (Pair "KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS" "KT1PuCU5UAoaX2Hjcns2SEmJWBC34tfLjzaS"))); TRANSFER_TOKENS; CONS; PUSH address "KT1AnDFRcdB652Jy5JFtmu7SampSPAzDkK7g"; CONTRACT %set_contracts (pair (pair address (pair address address)) (pair address (pair address address))); IF_NONE { PUSH int 176; FAILWITH } {}; PUSH mutez 0; PUSH (pair (pair address (pair address address)) (pair address (pair address address))) (Pair (Pair "KT1Ge5usHwAAH12PDxwP8FFYMdbMbXSRXSz4" (Pair "KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab" "KT1BUR5mjwBWzojKRqWrng8ASBh3N3LLV7NM")) (Pair "KT1KXvsh7vnPUkBj1oG1E3LUoFnKHsf7Wixo" (Pair "KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS" "KT1PvKziQx7pJhfr3FdvkhMPwCwLxjd32HkZ"))); TRANSFER_TOKENS; CONS; PUSH address "KT1C3T98TqCm38cHPauZ4SopkQ4torCsxgab"; CONTRACT %set_governance_params (pair (nat %escrow_amount) (pair (nat %vote_delay_blocks) (pair (nat %vote_length_blocks) (pair (nat %min_yes_votes_percentage_for_escrow_return) (pair (nat %timelock_execution_delay_blocks) (pair (nat %timelock_cancelation_delay_blocks) (pair (nat %super_majority_percentage) (pair %quorum_cap (nat %lower) (nat %upper))))))))); IF_NONE { PUSH string "DAO: Invalid entry point set_governance_params"; FAILWITH } {}; PUSH mutez 0; PUSH (pair nat nat) (Pair 800000000000000000 3744000000000000000); PUSH nat 80; PUSH nat 23040; PUSH nat 11520; PUSH nat 30; PUSH nat 28800; PUSH nat 11520; PUSH nat 500000000000000; PAIR 8; DIG 4; DROP; TRANSFER_TOKENS; CONS; PUSH address "KT1KShHvxW69YukaGetdgYRTw31d9BX8ijfF"; CONTRACT %update_max_release_period nat; IF_NONE { PUSH string "Savings pool: Invalid entry point update_max_release_period"; FAILWITH } {}; PUSH mutez 0; PUSH nat 1; TRANSFER_TOKENS; CONS; PUSH address "KT1HbzGokeEZ4hu1KRAAw2fyB61RCpBhQXKA"; CONTRACT %set_max_release_period nat; IF_NONE { PUSH string "Farm: Invalid entry point set_max_release_period"; FAILWITH } {}; PUSH mutez 0; PUSH nat 1; TRANSFER_TOKENS; CONS }
SHA256 Hash of the Michelson code
Please provide a SHA256 Hash of the above Michelson code here.
cded5802c33057c06785dec8942b36676a2c9b326bb180e3a80d6c19b83ba1df
We invite the youves community to comment and discuss this proposal. If there are questions, either post them here or contact us in the community channels on Telegram or Discord.
We are thrilled to explore new frontiers with you,
Thought, written and posted with ,
Your youves contributors, Florin & Markus.
Edited July 4th, 2023 - 12:22: fixed minor typos, changed details of the calculation example of the value of the liquidity token, changed title of change 4, added detail on how savers can redirect their funds into the new pool.
Edited July 12th, 2023 - 14:22: fixed minor typos, removed the detail info about new entrypoints of the new flat curve pool, added a link to the code of the new flat curve, added ghostnet instance of the new flat curve pool, added explanation for yyXTZ name selection, added the name “youves yield flat curve pool” or “youves yield uXTZ/XTZ pool”.
Edited July 26th, 2023 - 10:50: fixed minor typos, replaced ghostnet deployment with the final version (after security audit), added mainnet deployed contract, updated current pool numbers, added new flat curve pool contract KT1BFXgczFte2zftCTg7tL6Qk2capsFg6UFS
in paragraphs Change 4 > 4A, 4B, 4C, added links to smartPy and Michelson code of the lambdas of this YIP, added info about the security audit to be published on inference’s GitHub.
Edited July 26th, 2023 - 16:00: fixed typos, fixed headline of Change 2.