-
Notifications
You must be signed in to change notification settings - Fork 2
cergyk - LibUbiquityPool::mintDollar/redeemDollar reliance on outdated TWAP oracle may be inefficient for preventing depeg #13
Comments
1 comment(s) were left on this issue during the judging contest. auditsea commented:
|
1 comment(s) were left on this issue during the judging contest. auditsea commented:
|
Shouldn't the issue be marked with 'Sponsor disputed' label then if it is invalid? @rndquu @pavlovcik @molecula451 |
It probably makes more sense to ask @AuditSea (not sure if this is the corresponding GitHub handle.) |
Economically it doesn't make sense for a malicious user to do so. User is incentivised to arbitrage Dollar tokens hence even when metapool price is stale and a huge trade happens (i.e. a huge amount of Dollar tokens is minted in the Ubiquity pool) all secondary markets (uniswap, curve, etc...) will be on parity (in terms of Dollar-ANY_STABLECLON pair) after some time hence arbitrager will have to call Meanwhile I agree that the metapool's price can be stale but I don't understand how exactly minting "too many" Dollar tokens (keeping in mind that we get collateral in return) or burning "too many" Dollar tokens (keeping in mind that it reduces the Anyway fresh data is better than stale one and the fix looks like a one liner so perhaps it makes sense to implement it. So here we could remove liquidity from the curve's metapool with 0 values (as mentioned in the "recommendation" section) which updates cumulative balances under the hood. @gitcoindev @molecula451 What do you think? |
I have the same impression. Since this is easy to remediate with updating of cumulative balances I agree we could accept |
Escalate Some duplicates of this issue fail to explain the actual root cause of it, which is internal update function being called in the beginning of every action in the underlying metapool. Only valid duplicates of this issue are #68, #134, and #181. They all explain the core problem about curve metapool updating mechanism and provide recommendations regarding how to update underlying pool to solve the problem. Issues #34, #84, #92 and #187 are more related to Last 4 issues might be considered as separate group of valid issues or they might be invalidated depending on the judge's preference, but they should not be duplicates of this one. Kind regards. |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
@osmanozdemir1 I have internally discussed this with LSW and initially did deduplicated them as you mentioned. However, the watsons are technically not wrong per say by indicating an update required by using a stale time interval, so I decided to duplicate them. |
@nevillehuang Thanks for the response. I totally agree with you about watsons being technically not wrong. However, this issue is one step deeper than a regular stale price issue. Even non-stale prices (in terms of time interval) will be incorrect because of this issue. For example let's say staleness threshold is 4 hours: /* T-4 hours T-3 hours T0 current
|-----------------|---------------------------------------------------|
Latest action The time Ubiquity
in curve metapool updates & checks the price
|----------------------------------------------------|
Latest actions impact until now is not accounted
*/ In an example above, staleness interval check will not revert because it is inside the staleness threshold. However, the latest action's impact on the price is never accounted. If it is a large swap or deposit, 3 hours worth of impact of this action will be huge. Staleness check is not a solution for this problem. Only solution is somehow invoking the internal update function of the underlying curve metapool. And only issues I mentioned above explains this problem. Therefore, I strongly believe those other 4 issues regarding staleness check are valid issues but separate ones. Kind regards. |
Agreed, as an additional remediation to the individual TWAP issues, it would be reasonable to introduce a deviation check between the two oracles |
@Czar102 The chainlink oracle is not used for uAD, its used for the collateral. There is no uAD chainlink feed so the curve pool twap is used by checking the reserves and the price of that the twap returns does not determine the amount of the collateral tokens that the user receives, it just checks the thresholds |
@Czar102 But chainlink oracle not used for uAD pricing, there's no such feed. uAD price hardcoded to 1$ in the pool, only collateral chainlink feed used for calculating exchange rate assuming uAD worth 1$. |
By giving the right to users to mint/redeem collateral at the price given by the feed collateral/USD, the price of uAD is actually defined by this feed, so we can safely consider that the feed is also the real price collateral/uAD. Even though I agree with your point that the chainlink feed is not technically a uAD feed. |
Its an exchange rate that will always be 1 if the collateral is pegged to $1.00 and you will only receive more or less if the collateral price changes not the uAD price. The impact here is that it might be possible to mint/redeem outside of the thresholds, i dont get how you can “drain” the collateral. |
In the simplest way:
You are trying to invalidate this issue by saying the price calculation is correct while performing The bug is in I am genuinely surprised that we are still discussing the validity of a bug that directly impacts the total supply and mint/redeem decision of a stable token. uAD is a stable coin. It has certain rules to mint/burn. That rule is broken. |
@osmanozdemir1 Your report describes this issue really well although this comment #13 (comment) about the impact is wrong.
This is true but this still doesnt affect the price of uAD until its sold right? If the reserves were 99 and 101 then everyone is able to mint, the arbitrage bot would only need ~1 uAD to rebalance to the pool but what if an attacker just mints the max(50k uAD), isnt this the same problem? Although this rule is broken, you are not stealing anything, the protocol doesnt become insolvent or anything. Would be great if we could confirm with the sponsor what problem could this cause |
Just an example in terms of what problem could this cause: Let's assume TWAP price is 1.011 but the real price is 0.99.
Decision to mint/burn and increasing/decreasing token supply are most crucial things in a stable coin and these crucial actions are performed based on mint/redeem thresholds in this protocol. Possibility to mint/redeem outside of these thresholds is not an innocent issue. These thresholds will use outdated TWAP prices nearly all the time due to this issue because curve metapools are not highly active pools. They are not like uniswap pools. I provided both previous ubiquity metapool address and |
Minting the token will not decrease the price, minting and then selling the token in the curve pool is what will decrease the price, because this isnt profitable, no one would do this. If the real price was $0.99 then an arbitrage bot will buy uAD at a discounted price and then redeem and the pool will be updated because he just bought.
But the lookback window of the twap is 1 block so doesnt it just return the spot price and then use the current reserves? In that case if the price is 1.011 then an arbitrage bot will mint and sell right after the transaction that made the price 1.011. Described here #20 |
The real price I meant here is the real TWAP price after
Firstly, no it doesn't have to be 1 block. It is the difference between current timestamp and the last updated timestamp. #20 explains that it will be only 1 block if you update it in consecutive blocks. Secondly, no it doesn't return the spot price and that's whole point of my submission. It uses |
@osmanozdemir1 I see yeah, i somehow thought that the update is done after the tx. Not sure of the impact but ig medium is appropriate for using an incorrect value to check the thresholds. The comment by @Czar102 about the oracles is still incorrect tho. The impact of this issue is that most of the time it will use outdated twap price which can block or allow minting/redeeming. In #56 you would need a lot of funds just to allow/block minting and redeeming for a small amount of time which is not a problem unlike here where most of the time the wrong price will be used which will allow/block minting and redeeming |
Allowing minting won't increase total supply. No one would mint just because it's allowed when it will cause losses. But one can trigger curve
Just bcz TWAP is stale you can't assume whatever you want. What's probability of this state? I think such curve pools indeed can be stale for long time, but only when they balanced. Sorry, I really do not want to argue, just for @Czar102 to understand and answer my points. |
The protocol team fixed this issue in PR/commit ubiquity/ubiquity-dollar#893. |
After extensive discussions with the LSW and the Lead Judge, planning to resolve the escalation as previously intended (#13 (comment)), as the issue doesn't only cause a DoS, but may allow for an easy value extraction strategy from the protocol, similar to the one described in #17 and duplicates. Planning to accept the first and reject the second escalation. |
From #17
You can't swap because allowed only either mint or redeem. Also if pool works as expected it always lose value on mint/redeem, but it takes fee to mitigate this (btw this was my escalation point for #36 that fee actually used). Assume peg within desired range: 1.009, but mint is still open because twap is stale and returns 1.011, now you can mint 1 uAD = 1.009$ for 1$. But you pay same fee as usual. And usual mint expected to be more profitable and pool takes according fees. And with that fee mint is barely profitable. This is just my thoughts about the strategy and honestly I can't think of anything profitable here. @CergyK @nevillehuang But if there really is profitable strategy I want to learn it! |
@Czar102 @nevillehuang @CergyK I really dont undestand why we are trying to make #17 valid again which is a completely seperate issue from this one. As @0xLogos mentioned you are only able to mint or redeem so you cant sandwich the oracle update and it is not profitable.
Can you also please tell me since when is proposing 2 consecutive blocks considered easy? |
I think this comment is under wrong issue and nothing to do with this one. |
|
@nevillehuang The only way to obtain uAD is from the curve pool so you realistically cant have a huge amount like with 3crv. Can you also describe the whole attack path including the "profit" that the attacker gets combining #17 and #56? |
@0xArz I believe this is untrue based on your comment here and this statement here by sponsor. I think no further explanations is required from my end if not this discussion will be endless, better leave it to head of judging. |
Fine but they still have to get this uAD from somewhere but nvm. I just want you to realize how hard it is to perform an attack like this and looks like you cant even give me the attack path due to how hard the attack is. If you want to mint and then redeem you would have to manipulate the twap 2 times because as we mentioned you can either mint or redeem. This means that you would have to propose 2 consecutive blocks 2 times, if thats that easy is a 51% attack also a valid external vector to bypass thresholds? I really dont want to argue but im tired of having to fight back because this issue is getting validated just because you can "manipulate a twap" without actually stating the profit that the attacker gets, the extremely low circumstances and the huge amount of resources that the attacker needs. Talking about #17 or #56 here not #13 which is valid i believe. |
The outline of the attack, some details may be wrong since I haven't audited the code myself:
Will close this escalation today. |
When one of deposits/redeems are available, it's sufficient to propose 2 consecutive blocks only once. Also, simply providing liquidity after a rapid price change will help changing the operation permitted between mints and redeems. |
In that case the price of uAD has to be 1.01$ so the attacker is able to mint first. If you really think that all of these preconditions and the amount of resources that the attacker needs just to hedge a small amount of collateral is an easy value extraction strategy then i really dont know but looks like there is no point in continuing to explain why this issue is invalid so you can decide whatever you want. |
Result: @0xArz There are some preconditions, but the attack is possible and Medium severity is created for issues where loss of funds is limited, potentially due to many constraints. |
Escalations have been resolved successfully! Escalation status:
|
The Lead Senior Watson signed off on the fix. |
cergyk
medium
LibUbiquityPool::mintDollar/redeemDollar reliance on outdated TWAP oracle may be inefficient for preventing depeg
Summary
The ubiquity pool used for minting/burning uAD relies on a twap oracle which can be outdated because the underlying metapool is not updated when calling the ubiquity pool. This would mean that minting/burning will be enabled based on an outdated state when it should have been reverted and inversely
Vulnerability Detail
We can see that LibTWAPOracle has an update function to keep its values up to date according to the underlying metapool:
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibTWAPOracle.sol#L61-L102
And that this function is called when minting/burning uADs:
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibUbiquityPool.sol#L344
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibUbiquityPool.sol#L416
But the function update is not called on the underlying metapool, so current values fetched for it may be stale:
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibTWAPOracle.sol#L134-L136
Impact
A malicious user can use this to mint/burn heavily in order to depeg the coin further
Code Snippet
Tool used
Manual Review
Recommendation
Call the function:
On the underlying metapool the twap is based on, with only zero values, to ensure that the values of the pool are up to date when consulted
The text was updated successfully, but these errors were encountered: