Open code423n4 opened 1 year ago
kirk-baird marked the issue as primary issue
vaporkane marked the issue as sponsor confirmed
vaporkane marked the issue as disagree with severity
This is a valid issue in that it may cause rounding errors.
However, the calculations where division are involved use BASE_UINT
to increase the value of the numerator by 1e18. This minimises the impact of rounding issues to the order of Wei. As a result there is negligible impact from rounding errors and I consider this to be a low severity issue.
kirk-baird changed the severity to QA (Quality Assurance)
kirk-baird marked the issue as grade-a
vaporkane marked the issue as sponsor acknowledged
Lines of code
https://github.com/code-423n4/2023-05-xeth/blob/main/src/wxETH.sol#L82 https://github.com/code-423n4/2023-05-xeth/blob/main/src/wxETH.sol#L114
Vulnerability details
Potential loss of precision in stake and unstake actions of wxETH
The calculations involved in the stake and unstake actions can potential suffer from precision loss, affecting the number of minted wxETH shares or the amount of redeemed xETH.
Impact
The
stake()
function present in the wxETH can be used to stake xETH tokens and get in return a number of wxETH tokens, that represent the user's share in the pool. The calculation of the number of shares based on the amount of assets can be found in thepreviewStake()
andexchangeRate()
functions:https://github.com/code-423n4/2023-05-xeth/blob/main/src/wxETH.sol#L82-L88
https://github.com/code-423n4/2023-05-xeth/blob/main/src/wxETH.sol#L202-L216
As we can see in the previous snippets,
previewStake()
will basically divide the amount of assets by the exchange rate, but the exchange rate is also a division of the total assets (cashMinusLocked
) by the total supply of the shares (_totalSupply
). Focusing on the general case when_totalSupply > 0
, the calculation can be summarized as:We have a division where the denominator is also a division, which implies a potential loss of precision.
Similarly, in the
unstake()
function,previewUnstake()
is used to calculate the redeemed amount of xETH given a number of wxETH shares:https://github.com/code-423n4/2023-05-xeth/blob/main/src/wxETH.sol#L114-L120
Expanding the calculation, we have:
Arriving again at a similar case of potential loss of precision.
Recommendation
The calculations can be simplified in order to avoid intermediate divisions and loss of precision. For staking,
previewStake()
can be refactored as:While for unstaking,
previewUnstake()
can be refactored as:Assessed type
Decimal