The issue was a loss of precision of three different kinds.
(1) (a/b)*c <= a*c/b in the slippage calculations in Reth.withdraw(), Reth.deposit() and SfrxEth.withdraw().
(2) a/k + b/k <= (a + b)/k in the calculations of underlyingValue, totalStakeValueEth in SafEth.stake().
(3) a/(b/c) >= a*c/b in the calculation of mintAmount in SafEth.stake().
Mitigation review
The instances of (1) in Reth.withdraw() and SfrxEth.withdraw() have been correctly refactored.
But Reth.deposit() is now:
All of (2) and (3) remain unaltered however. This duplicate of M-01 provides an explicit refactoring of stake() which solves them. However, because of the introduction of SafEth.approxPrice() this refactoring will have to be reworked. Technically, this is an entirely new issue, which is why this is reported in detail in "Rounding loss in and with approxPrice()".
https://github.com/asymmetryfinance/smart-contracts/blob/ec582149ae9733eed6b11089cd92ca72ee5425d6/contracts/SafEth/SafEth.sol#L87-L119
Mitigated issue
M-01: Division before multiplication truncate minOut and incurs heavy precision loss and result in insufficient slippage protection
The issue was a loss of precision of three different kinds. (1)
(a/b)*c <= a*c/b
in the slippage calculations inReth.withdraw()
,Reth.deposit()
andSfrxEth.withdraw()
. (2)a/k + b/k <= (a + b)/k
in the calculations ofunderlyingValue
,totalStakeValueEth
inSafEth.stake()
. (3)a/(b/c) >= a*c/b
in the calculation ofmintAmount
inSafEth.stake()
.Mitigation review
The instances of (1) in
Reth.withdraw()
andSfrxEth.withdraw()
have been correctly refactored. ButReth.deposit()
is now:minOut
is still of the form(a/b)*c
. It should be refactored toidealOut
may then be refactored to(which has the same precision.)
All of (2) and (3) remain unaltered however. This duplicate of M-01 provides an explicit refactoring of
stake()
which solves them. However, because of the introduction ofSafEth.approxPrice()
this refactoring will have to be reworked. Technically, this is an entirely new issue, which is why this is reported in detail in "Rounding loss in and with approxPrice()".