Platform: Code4rena
Start Date: 14/07/2022
Pot Size: $25,000 USDC
Total HM: 2
Participants: 63
Period: 3 days
Judge: PierrickGT
Total Solo HM: 1
Id: 147
League: ETH
Rank: 32/63
Findings: 1
Award: $46.40
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: hickuphh3
Also found by: 0x29A, 0x52, 0xNazgul, Chom, Deivitto, ElKu, Funen, IllIllI, Meera, ReyAdmirado, SooYa, TomJ, Trumpero, Waze, __141345__, ak1, asutorufos, c3phas, cRat1st0s, csanuragjain, delfin454000, exd0tpy, fatherOfBlocks, hake, hansfriese, horsefacts, hyh, karanctf, kenzo, kyteg, ladboy233, pashov, peritoflores, rajatbeladiya, rbserver, reassor, rokinot, simon135, wastewa
46.3982 USDC - $46.40
Precision is now can be lost due to division done in _calcPayout() ahead of multiplication in resulting collateral amount calculation.
_calcPayout() is used in payBase() and payFYToken(), also in calcPayout() for calculation of the liquidator and auctioneer cuts.
Setting the severity to medium as that can constitute diminished returns for liquidator and auctioneer compared to the stated linear proportion, i.e. the system behavior diverts from the expected and produces losses for counterparts.
Resulting collateral amount in _calcPayout() is calculated by performing the division first:
uint256 inkAtEnd = uint256(artIn).wdiv(auction_.art).wmul(auction_.ink);
This constitutes (artIn * 1e18) / auction_.art * auction_.ink / 1e18 (1)
expression.
Rewriting this with multiplication by auction_.ink
first yields artIn * auction_.ink / 1e18 * 1e18 / auction_.art (2)
.
As fyToken amount auction_.art
is generally greater than 1e18
(i.e. usual sum is greater than 1 unit; can be magnitudes greater), the precision is reduced by doing the division first.
As a corner case example, if artIn = 1e18, auction_.art = auction_.ink = 1e19*e18
, (1) is (1e18 * 1e18) / (1e19*1e18) * (1e19*1e18) / 1e18 = 0
, (2) is 1e18 * (1e19*1e18) / 1e18 * 1e18 / (1e19*1e18) = 1e18
, i.e. inkAtEnd will be rendered to 0.
inkAtEnd is then used for liquidator and auctioneer rewards calculation:
uint256 inkAtEnd = uint256(artIn).wdiv(auction_.art).wmul(auction_.ink); liquidatorCut = inkAtEnd.wmul(proportionNow); if (auction_.auctioneer != to) { auctioneerCut = liquidatorCut.wmul(auctioneerReward); liquidatorCut -= auctioneerCut; }
Consider switching to an equivalent expression that have multiplication performed first:
- uint256 inkAtEnd = uint256(artIn).wdiv(auction_.art).wmul(auction_.ink); + uint256 inkAtEnd = uint256(artIn).wmul(auction_.ink).wdiv(auction_.art);
#0 - alcueca
2022-07-21T10:52:36Z
Duplicate of #166
#1 - PierrickGT
2022-07-29T10:16:25Z
Read the following comment to understand why this issue has been labelled as invalid: https://github.com/code-423n4/2022-07-yield-findings/issues/166#issuecomment-1199108157
#2 - PierrickGT
2022-08-08T20:20:19Z
Read the following comment to understand why the invalid
tag has been removed and why this issue has been downgraded to QA report: https://github.com/code-423n4/2022-07-yield-findings/issues/166#issuecomment-1208567232