Platform: Code4rena
Start Date: 16/02/2023
Pot Size: $144,750 USDC
Total HM: 17
Participants: 154
Period: 19 days
Judge: Trust
Total Solo HM: 5
Id: 216
League: ETH
Rank: 2/154
Findings: 3
Award: $11,668.80
π Selected for report: 1
π Solo Findings: 0
8788.114 USDC - $8,788.11
updateRewardSum function call _computeRewardsPerUnitStaked with _debtToOffset set to 0. Meaning that the assignment L531 will revert if lastLUSDLossError_Offset != 0
(which is likely the case) because we try to assign a negative value to an uint.
_rebalance() will be definitely DOS if the profit is greater than the yieldClainThreshold β vars.profit != 0.
Because they call _rebalance() all these functions will be DOS :
In BorrowerOperations
100% DOS
- openTrove
- closeTrove
- _adjustTrove
- addColl, withdrawColl
- withdrawLUSD, repayLUSD
In TroveManager
80% DOS
- liquidateTroves
- batchLiquidateTroves
- redeemCloseTrove
Context : the vault has compound enough profit to withdraw. (here)
Alice initiates a trove liquidation. offset() in StabilityPool
is called to cancels out the trove debt against the LUSD contained in the Stability Pool.
A floor division errors occur so now lastLUSDLossError_Offset is not null.
Now, every time _rebalance() is called the transaction will revert.
In StabilityPool.sol#L504-L544, just skip the floor division errors calculation if _debtToOffset == 0
if(_debtToOffset != 0){ [StabilityPool.sol#L526-L538](https://github.com/code-423n4/2023-02-ethos/blob/73687f32b934c9d697b97745356cdf8a1f264955/Ethos-Core/contracts/StabilityPool.sol#L526-L538) }
#0 - c4-judge
2023-03-09T15:20:31Z
trust1995 marked the issue as unsatisfactory: Insufficient proof
#1 - c4-judge
2023-03-20T10:32:23Z
trust1995 marked the issue as satisfactory
#2 - c4-judge
2023-03-20T10:33:32Z
trust1995 marked the issue as primary issue
#3 - c4-judge
2023-03-20T15:49:12Z
trust1995 marked the issue as selected for report
#4 - liveactionllama
2023-04-20T17:51:48Z
Per discussion with sponsor and also their comment here, adding sponsor confirmed
label.
2737.8355 USDC - $2,737.84
Description
Due to decimal difference not taken into account, the increaseF_Collateral() function from LQTYStaking
contract will not increase the reward per unit staked.
Impact
If WBTC is used in collateral ; when collecting the 0.5% fee (here) or when crediting the vault yield (here) and under this conditions :
$collFeePerLQTYStaked = \frac{collWBTC*1^{18}}{totalLQTYStaked} <1 β collWBTC < \frac{totalLQTYStaked}{1^{18}}$
The LQTYStaking
contract will not be credited, making these tokens to be lost forever and the LQTY stakers not receiving their rewards.
Because WBTC has 8 decimals and LQTY has 18 decimals, itβs easy to find values that satisfy this condition.
POC
We call increaseF_Collateral(address _collateral, uint collFee)
because we want to increase the reward per unit staked in the LQTYStaking
contract.
_collFee = 0.001 WBTC = 1e5 wsatoshi
totalLQTYStaked = 1_000_000 LQTY = 1e24 wei
With these values the bug condition is verified :
Mitigation
One solution could be to keep the rounding error in a variable and credit the reward to stakers when it can be apply. Similarly to the StabilityPool
contract with the lastCollateralError_Offset variable. StabilityPool.sol#L524-L541
#0 - c4-judge
2023-03-09T15:16:23Z
trust1995 changed the severity to 2 (Med Risk)
#1 - c4-judge
2023-03-09T15:16:30Z
trust1995 marked the issue as satisfactory
#2 - c4-judge
2023-03-09T15:16:34Z
trust1995 marked the issue as primary issue
#3 - tess3rac7
2023-03-15T00:45:15Z
This is a valid issue for sure. Severity can be debated between medium and high. It could be medium in that it would only result in losing some rewards for stakers (no staked principal lost). But it's high if you consider those rewards as something owed to the stakers that they are now at a loss for. Requesting judge review to determine severity.
#4 - c4-sponsor
2023-03-15T00:45:22Z
tess3rac7 requested judge review
#5 - trust1995
2023-03-20T11:37:08Z
Personally view loss of yield as high severity (in line with Immunefi classification).
#6 - c4-judge
2023-03-20T11:37:18Z
trust1995 changed the severity to 3 (High Risk)
#7 - c4-judge
2023-03-20T16:12:51Z
trust1995 marked the issue as selected for report
#8 - c4-judge
2023-03-23T10:13:40Z
trust1995 marked issue #285 as primary and marked this issue as a duplicate of 285
π Selected for report: GalloDaSballo
Also found by: 0xBeirao, 0xRobocop, AkshaySrivastav, KingNFT, MiloTruck, PaludoX0, bin2chen, hansfriese, imare, kaden
142.8544 USDC - $142.85
Ethos core contracts are not designed to deal with losses. This is because vaults invest in strategies that are not designed to lose money.
Globally, this system doesn't handle losses, but let's take an example to show why this is critical:
Let's say a vault strategy is hacked and 10% of the total collateral disappears.
This assignment will now revert every time _rebalance()
is called : ActivePool.sol#L251
vars.profit = vars.sharesToAssets.sub(vars.currentAllocated);
Now sharesToAssets < currentAllocated
. Because we try to assign a negative value to an uint
, _rebalance will now always revert making the system DOS :
In BorrowerOperations
100% DOS
TroveManager
80% DOSThis will probably trigger fear in users and they will start selling their LUSD on the secondary markets causing a depeg. Probably nobody will want to buy back LUSD since the system is DOS users are no longer incentivises to maintain the peg.
Note that a hack or bug in a strategy that results in a loss of funds of just a few basis points can trigger this massive DOS.
With 2 examples we will figure out why this is really concerning
1st scenario (the repairable one) :
Context : TVL = 1 000 000 ; lossPercentage = 0.01% β loss = 10 000$
Here 10k have been hacked from a strategy. The loss is small but the protocol DOS anyway. The Ethos team can fix the protocol by manually sending 10k$ of the underlying collateral to the vault that has been hacked in order artificially increase the share price.
Impact : protocol DOS during 1 day and Ethos loss 10 000$
2nd scenario :
Context : TVL = 1B ; lossPercentage = 10% β loss = 100M$
Now the team will have to send 100M to the vault to repair the protocol. If they never find the money the other 900M$ will be stuck in the protocol forever. Making users lose 100% of their investment instead of only 10%.
This scenario needs to be handled properly.
A safer system would be to spread the loss over all investors.
If we take the example above, everyone loses 10%. The TCR will fall, causing some troves to be liquidated. If the loss is greater than 10%, some troves may be underwater. Liquidity providers of stability pool will absorb the loss, but at least the integrity of the system is maintained and the LUSD remains pegged.
Even though the strategies invested in are the safest in the industry, I think it's worth implementing a loss-handling mechanism to ensure that the protocol remains robust over time.
#0 - c4-judge
2023-03-08T15:48:09Z
trust1995 marked the issue as duplicate of #747
#1 - c4-judge
2023-03-08T15:48:15Z
trust1995 marked the issue as satisfactory
#2 - c4-judge
2023-03-20T15:51:22Z
trust1995 changed the severity to 2 (Med Risk)