code-423n4 / 2023-06-lybra-findings

8 stars 7 forks source link

`LybraConfigurator::distributeRewards` assumes that `stableToken` has `6` decimals #763

Open code423n4 opened 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/configuration/LybraConfigurator.sol#L298-L305

Vulnerability details

In LybraConfigurator::distributeRewards, if there is enough EUSD balance, some part of income may be exchanged to another stablecoin, called stableToken. It is only exchanged when premiumTradingEnabled && price > 1005000, where price = curvePool.get_dy_underlying(0, 2, 1e18) and according to Curve Docs (https://curve.readthedocs.io/factory-pools.html), get_dy_underlying returns amount of tokens received. So, in essence, function will check how much of stablecoins will the contract receive for 1 EUSD and if the amount is too low (<= 1005000 = 1.005 in case of 6 - decmial tokens), the swap won't take place and EUSDs will just be transfered to lybraProtocolRewardsPool.

It will work fine for 6 - decimal stablecoins, like USDC, but will not work correctly in case of those that have more decimals, for instance BUSD (has 18) - of course, BUSD will probably cease to exist in several months, but, still, stablecoins with 18 decimals exist.

In case of such stablecoins, the condition price <= 1005000 will almost always be false, even if 1 EUSD = 0.000001 BUSD, so the protocol may perform a very unprofitable swap (of course, it may also be 1 EUSD = 0.95 BUSD due to a temporary depeg - protocol will still lose value).

Impact

Protocol may do unprofitable swaps, thus value is leaked. Since there is a leak of value and it's conditional (non-6-decimal stablecoin has to be used), the issue is classified as Medium.

Proof of Concept

  1. BUSD is used as a stablecoin in configurator.
  2. There is a temporary depeg of EUSD - it happens from time to time; it also happened in the past to other collateralised stablecoins, such as DAI (when USDC depegged). So, assume that 1 EUSD = 0.95 BUSD = $0.95.
  3. Assume that premiumTradingEnabled is true.
  4. Then, the contract will perform a swap despite the fact that it should only perform it when the price of EUSD is above or equal $1.005:

https://github.com/code-423n4/2023-06-lybra/blob/7b73ef2fbb542b569e182d9abf79be643ca883ee/contracts/lybra/configuration/LybraConfigurator.sol#L298-L305

Tools Used

VS Code

Recommended Mitigation Steps

Change price <= 1005000 in if to price <= 1005 * 10**stableToken.decimals() / 1000.

Assessed type

Decimal

c4-pre-sort commented 1 year ago

JeffCX marked the issue as primary issue

c4-sponsor commented 1 year ago

LybraFinance marked the issue as sponsor disputed

LybraFinance commented 1 year ago

Our plan is to only swap for USDC.

c4-judge commented 1 year ago

0xean changed the severity to QA (Quality Assurance)

c4-sponsor commented 1 year ago

LybraFinance marked the issue as sponsor acknowledged

c4-judge commented 1 year ago

0xean marked the issue as grade-a