-
Notifications
You must be signed in to change notification settings - Fork 91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pairing Dollar with 3CRV will still make Dollar follow a price of $1.03, even if StableSwapMetaNG pools are used #931
Comments
Check the following Curve's metapools:
All of them contain a pair of a USD pegged stablecoin + 3CRV LP. The |
Yeah I checked them. def __init__(
...
):
self.last_prices_packed = self.pack_2(10**18, 10**18)
...
This is why pools will always return a price of 1, even if they are empty. Every time an interaction that updates the oracle (exchange/add_liquidity_remove_liquidity...) with the pool takes place, the pool invariant will be computed with a combination of the amplifier, the pool's balances and the def add_liquidity(
_amounts: uint256[N_COINS],
_min_mint_amount: uint256,
_receiver: address = msg.sender
) -> uint256:
...
amp: uint256 = self._A()
old_balances: uint256[N_COINS] = self._balances()
rates: uint256[N_COINS] = self._stored_rates()
# Initial invariant
D0: uint256 = self.get_D_mem(rates, old_balances, amp)
... The def add_liquidity(
_amounts: uint256[N_COINS],
_min_mint_amount: uint256,
_receiver: address = msg.sender
) -> uint256:
...
xp: uint256[N_COINS] = self._xp_mem(rates, new_balances)
...
# we do unsafe div here because we already did several safedivs with D0
mint_amount = unsafe_div(total_supply * (D1 - D0), D0)
self.upkeep_oracles(xp, amp, D1) Knowing that def _stored_rates() -> uint256[N_COINS]:
"""
@notice Gets rate multipliers for each coin.
@dev If the coin has a rate oracle that has been properly initialised,
this method queries that rate by static-calling an external
contract.
"""
rates: uint256[N_COINS] = [rate_multiplier, StableSwap(BASE_POOL).get_virtual_price()]
...
As we can see, rates[0] (the rate multiplied by the Dollar's pool balance) is harcoded to This means that every time the pool invariant or xp is computed, rates will use the 3CRV's virtual price (not set at $1) to derive the ideal state of the pool. As per the prices in the pools you showed, probably they are still set at prices near 1 because there haven't been many trades on them, but if they were to be traded frequently, price should be encouraged to follow 3CRV's price. |
If we move to CurveStableSwapNG then is it ok to use collateral tokens from LibUbiquityPool? So we'll:
Or it is better to create |
I wouldn't create the pool with the same collateral tokens. I'd rather go with USDC, but if you want to avoid centralized stables then sUSD is also a good option. The main problem here is you need to have a 100% trust that the stablecoin you are pairing with will keep its peg, and become 100% reliant on it. I would query a Chainlink oracle to check sUSD's price as well, and compare it after querying the curve pool price to properly appraise Dollar |
You mean:
Right? |
You don't really need to verify that they're in the same threshold, but rather extract the $ value for sUSD from the response received by Chainlink. For example, let's say the curve pool returns 1 Dollar = 1.01 sUSD. However, querying chainlink returns 1 sUSD = $0.99. This will mean that Dollar is not worth $1.01, but $0.9999 (extracted from the multiplication between sUSD and CL price, which is 1.01*0.99). |
As far as I understand if we multiply chainlink price by curve price we get more actual price compared to the price from Curve's oracle. Is it ok if right now we'll simply use the Curve's oracle price and add "chainlink multiplication" price later? We have an epic of using multiple oracles for fetching prices and this "chainlink multiplication" fits into that issue. |
Hmm, do you have an example of such a case where more price was obtained?
Yes, I think that for the initial phase of the protocol that should do, it could be added later although highly recommend to add it in the beginning. |
I got what you mean. Yes, you're right, so if SUSD depegs then:
@0x4007 Is it ok if we create a new Curve's pool with I read the spec. Why not just use LUSD instead of sUSD? |
One more question regarding price oracle indexes, just want to make it clear. So we need to:
Correct? |
Yes, that is correct! Just make sure index 0 will be set to sUSD and index 1 to Dollar when creating the pool |
It seems there is no SUSD/USD price feed, there is this one https://etherscan.io/address/0xad35bd71b9afe6e4bdc266b345c198eadef9ad94 but it is not live. I guess we'll have to fetch SUSD/ETH (which does have a live price feed) and then ETH/USD to get a SUSD/USD quote. |
True, I checked it wrong and thought the feed was for USD. |
Why are we concerned with implementing sUSD features if it's not even planned for the mid term? I expected we can get far with only LUSD. |
@0x4007 We want to move from @0xadrii Back to this question, as far as I understand we could use |
Exactly, if you're willing to take the risk and only consider LUSD initially then the mechanics should work as if the collateral token was different or if the pool was paired with a different token. Still, the Chainlink check should be done to ensure the actual $ price is correct. |
Your sentence is not clear. Using The benefit of using 3CRV is that we have better liquidity for the other popular stablecoins. But if we control the liquidity then in essence it is a form of our collateral. It would be more "pure" to only support |
! action has an uncaught error |
Recommendation:
The best solution to achieve an actual peg to $1 would be to use Chainlink price feeds instead. or to pair Dollar with a different asset that is actually pegged to $1 rather than 3CRV, given that currently the pool price will tend to follow 3CRV's price, which currently trades at $1.03.
Originally posted by @0xadrii in #893 (comment)
The text was updated successfully, but these errors were encountered: