-
Notifications
You must be signed in to change notification settings - Fork 2
cergyk - LibTWAPOracle::update Providing large liquidity will manipulate TWAP, DOSing redeem of uADs #56
Comments
@rndquu @pavlovcik @molecula451 what do you think about this one? Technically possible, but would likely require lots of staked ETH. I am wondering if this is just hypothetical and controlling 2 blocks would require funds of e.g. Coinbase size. If this is the case, then perhaps impact is high but probability is very low. There are currently ~900k ETH validators https://beaconcha.in/charts/validators with each staked at least 32 ETH. |
I spent some time looking through our old issues and discussions but unfortunately I couldn't find my writeup on this. Basically as I recall, after The Merge there was a research report that proved how a two-consecutive-block TWAP attack could be performed with a realistic amount of funds. Unfortunately I don't remember the conclusion of how to mitigate. |
TWAP window here is ~8 minutes. If we take a 30 minutes TWAP window (suggested everywhere) we get Overall this seems to be a duplicate of #20 since increasing the TWAP window fixes the issue (to some extent). |
So, as far as I understand, the core issue is that the curve metapool uses accumulated balances instead of accumulated spot prices hence the TWAP is not as accurate as it could be. I agree that it could be improved but disagree with the "high" severity. |
Escalate
In this issue attacker would need a large amount of funds (exactly 15 times more than curve pool reserves according to example) and control over 2 consecutive block (feasible, but very difficult) just to dos withdrawals for short time (in example 40 blocks = 12*40/60 = 8 min). |
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. |
@CergyK any comments? |
I also want to note that the proposed solution is quite difficult to implement correctly and I believe that it is an acceptable risk to leave it as is |
Is uAD TWAP manipulatable? |
@0xLogos, even after addressing issue 20, the system remains susceptible to manipulation. In a standard arbitrage situation, specific conditions enable arbitrageurs to profit. However, #212 deviates from this. Here, the attacker can intentionally trigger redemptions to acquire collateral at a lower price by influencing the uAD price. This means the attacker can engineer favorable conditions, rather than relying on chance, effectively manipulating the protocol to their advantage. |
from #72 (comment) Doesn't look like manipulation |
The attacker can lower the price to enable redeems as they can now get collateral for lower price. If this isn't manipulation, then what is it? Edit: improved the wording in the comment. |
@0x3agle but why would you even need to manipulate the twap? I think your issue describes pretty much the same thing as #72 and the root cause is the same - collateral depegging. The attack will be possible without the TWAP manipulation(assuming the the price of uAD stays at $1.00) Total Spent: 97,000 LUSD (for minting uAD) + ~$50 (Slippage for swapping twice [uAD to 3CRV then 3CRV to uAD]) There is no actual profit here, because 97,000 LUSD at $1.03 is worth the same as 101,000 LUSD at $0.99 Also i believe the redeemPriceThreshold is $1.01 not $0.99, it wouldnt make sense to not allow users to redeem when the price is $1.00 right? Would be great if sponsor could confirm this I think what you are saying is that you can manipulate the price so that redeems are opened but i believe that the redeemPriceThreshold is $1.01 so you dont have to manipulate anything but just wait when the collateral drops |
Good point |
This is called as hedging. By applying this strategy, the attacker offsets the losses at the cost of protocol. Therefore, the attacker does not lose any value. Regarding redeem threshold: you are saying that to enable redeem, the uAD should go up instead of down. What will you do to level the uAD back? - Mint. When uAD goes down to $0.99, the supply is more demand is less. Therefore we need to burn the uAD to match supply and demand. Hence redeem will be enabled if uAD goes below $0.99 |
require(
getDollarPriceUsd() >= poolStorage.mintPriceThreshold,
"Dollar price too low"
);
So you are saying that the mintPriceThreshold is $1.01? How will then users be able to mint uAD when the curve pool was just created and the price is $1.00? $0.99 for minting and $1.01 for redeeming makes more sense. Same impact like in #72 btw |
When the pool is first deployed, users can neither mint or redeem. The demand for uAD arises. Users start buying it using 3CRV from curve pool. So, eventually the twap will show an increased price. Let’s say $1.02 How will redeems be unlocked? Now redeems will be enabled (mints are disabled) which will give you more collateral for same uAD. Again arbitrage, leading to curve pool balance. Stabilising price of uAD back to $1- disabling any mints or redeems |
hey @pavlovcik @gitcoindev @rndquu what are the correct thresholds that will be used? In the tests the mintPriceThreshold is set to $1.01 and the redeemPriceThreshold is set to $0.99 which means that when the price is $1.00 users will not be able to mint or redeem uAD. This doesnt really makes sense as users are supposed to be able to obtain uAD on a 1:1 ratio or is the UbiquityPool just going to be used to rebalance the price? Thank you in advance! |
Minting above $1.00 and redemptions below $1.00. The threshold should be adjustable so for now
That's a good question. We have an application to manage and incentivize distributed teams which offers incentives to settle payments in our Ubiquity Dollars. Assuming that there is some demand generated for our Ubiquity Dollars with our DevPool system, we should easily be able to move the price above the threshold. If there is no demand, I think it makes sense for the protocol to not respond with incentives to change the supply. |
It seems the escalation is based on the fact that a relatively short (?) duration was used in the example. |
Users may also get Dollar( |
@pavlovcik @rndquu First of all we need to know max aceptable by protocol team time that pool can be DOSed taking into account that admin can in any time prevent DOS by adjusting threshholds. Based on example you need 100K pool liquidity * 15 = 1.5M$ AND control over 2 block to DOS for 8 min (correct me if i am wrong) |
I don't think that any time >0 seconds is an acceptable DOS duration for any protocol :) |
Sorry but this is not true. There's no perfect systems, you have to come up with suitable threat model. Also I believe that in order to understand the severity of the issue you need to somehow evaluate the difference between calculating price based on time average balances and using time average price like uni v3 because this is proposed solution. (If you have control over 2 block you can do similar thing with prices swapping back and forth in 2 blocks) My point is example in report is very vague and there's need at least for more realistic PoC and ideally comparison with proposed solution. |
I believe oracle manipulation can have a more severe impact than a DoS for a few minutes, see #13 (comment). Planning to reject the escalation and leave the issue as is. |
#13 (comment) is inaccurate |
Thank you @0xLogos for noting a mistake in my previous statement. We are also discussing the severity of TWAP manipulation on #59 right now, it may be relevant. |
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 leave this issue a Medium severity one, as it 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 reject the escalation and leave the issue as is. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
The Lead Senior Watson signed off on the fix. |
cergyk
high
LibTWAPOracle::update Providing large liquidity will manipulate TWAP, DOSing redeem of uADs
Summary
The twap oracle used by ubiquity does not compute a TWAP (Time weighted average price) but an instant price based on time weighted average of balances, and thus is more vulnerable to manipulation by an actor temporarily allocating a large amount to the metapool.
Vulnerability Detail
We can see the
LibTWAPOracle::update()
calls onIMetapool::get_twap_balances(uint256[2] memory _first_balances, uint256[2] memory _last_balances, uint256 _time_elapsed)
which gets the time-weighted average of the pool reserves given time_elapsed and cumulative balances.Then the time-weighted average is deduced by using the average of reserves over the
time_elapsed
. However we can see that a user with a large amount of capital and controlling 2 consecutive blocks can either add large liquidity in an imbalanced way in block N, and remove in block N+1.In that case the
higher
reserves ratio will have a higher weight in the computation and will last for many blocks.Scenario
1/ In block N-1:
Metapool contains 10 of uAD and 10 of 3CRV, the price is balanced, and withdrawals of uAD are accepted.
2/ In block N:
Alice updates both metapool twap and ubiquityPool twap.
Alice provides 100 uAD and 200 3CRV to the pool, now reserves are 110 uAD and 210 3CRV
3/ In block N+1:
Alice removes the previously added liquidity putting the reserves back to 10 uAD and 10 3CRV, but does not updates UbiquityPool right away.
4/ In block N+40:
Alice updates both Metapool and ubiquity TWAP oracle,
Let's see the value which is computed for the returned TWAP:
uAD cumulative reserve difference = 12*110+12*40*10 = 6120
3CRV cumulative reserve difference = 12*210+12*40*10 = 7320
We can see that the reserves are still very imbalanced even 40 blocks after the 2 blocks manipulation, blocking withdrawals, because uAD price versus 3CRV is too high:
https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibUbiquityPool.sol#L418-L421
Impact
A malicious user with access to considerable capital and controlling two consecutive blocks (feasible since the merge), can DOS the withdraw functionality of UbiquityPool for many blocks.
Code Snippet
Tool used
Manual Review
Recommendation
Find a way to compute the twap of the price (as Uniswap v3 does), instead of using twap of balances as a proxy
The text was updated successfully, but these errors were encountered: