Platform: Code4rena
Start Date: 10/05/2022
Pot Size: $50,000 USDC
Total HM: 13
Participants: 100
Period: 5 days
Judge: HardlyDifficult
Total Solo HM: 1
Id: 122
League: ETH
Rank: 73/100
Findings: 1
Award: $54.89
π Selected for report: 0
π Solo Findings: 0
π Selected for report: hubble
Also found by: 0x1337, 0x1f8b, 0x4non, 0xDjango, 0xf15ers, 0xsanson, 242, Aits, AlleyCat, Bludya, BondiPestControl, BouSalman, BowTiedWardens, CertoraInc, Cityscape, Czar102, FSchmoede, Funen, Hawkeye, IllIllI, JDeryl, Kenshin, Kumpa, MaratCerby, MiloTruck, Picodes, Ruhum, TrungOre, VAD37, WatchPug, Waze, antonttc, bobirichman, catchup, cccz, cryptphi, csanuragjain, delfin454000, dipp, dirk_y, djxploit, eccentricexit, ellahi, fatherOfBlocks, hake, hansfriese, hickuphh3, horsefacts, hyh, jah, joestakey, mics, minhquanym, pedroais, pmerkleplant, radoslav11, reassor, rfa, robee, seanamani, shenwilly, shung, sikorico, sorrynotsorry, sseefried, z3s
54.8931 USDC - $54.89
https://github.com/code-423n4/2022-05-cally/blob/main/contracts/src/Cally.sol#L406-L423
Solidity integer division might truncate. As a result, performing multiplication before division can sometimes avoid loss of precision.
Cally.getDutchAuctionStrike(uint256,uint32,uint256)
(Cally.sol#406-423) performs a multiplication on the result of a division:
-progress = (1e18 * delta) / AUCTION_DURATION
(Cally.sol#418)
-auctionStrike = (progress * progress * startingStrike) / (1e18 * 1e18)
(Cally.sol#419)
function getDutchAuctionStrike( uint256 startingStrike, uint32 auctionEndTimestamp, uint256 reserveStrike ) public view returns (uint256 strike) { /* delta = max(auctionEnd - currentTimestamp, 0) progress = delta / auctionDuration auctionStrike = progress^2 * startingStrike strike = max(auctionStrike, reserveStrike) */ uint256 delta = auctionEndTimestamp > block.timestamp ? auctionEndTimestamp - block.timestamp : 0; uint256 progress = (1e18 * delta) / AUCTION_DURATION; uint256 auctionStrike = (progress * progress * startingStrike) / (1e18 * 1e18); // max(auctionStrike, reserveStrike) strike = auctionStrike > reserveStrike ? auctionStrike : reserveStrike; }
In general, it's usually a good idea to re-arrange arithmetic to perform multiplication before division, unless the limit of a smaller type makes this dangerous.
manual analysis
Consider ordering multiplication before division.
#0 - outdoteth
2022-05-15T21:16:11Z
No exploit is given. The precision here is not critical so we disagree with the severity.
#1 - HardlyDifficult
2022-05-22T15:14:07Z
This is often considered a best practice, but without details about a potential exploit or how severe the rounding error would be using reasonable inputs - this is a 1 (Low). Converting to a QA report for the warden.