Yield Witch v2 contest - peritoflores's results

Fixed-rate borrowing and lending on Ethereum

General Information

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

Yield

Findings Distribution

Researcher Performance

Rank: 33/63

Findings: 1

Award: $44.80

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

44.8039 USDC - $44.80

Labels

QA (Quality Assurance)
old-submission-method

External Links

Lines of code

https://github.com/code-423n4/2022-07-yield/blob/6ab092b8c10e4dabb470918ae15c6451c861655f/contracts/Witch.sol#L594

Vulnerability details

Impact

Collateral rounding error

Proof of Concept

In the following line there is a division before multimplication. As artIn < auction_.art then this division will be zero.

uint256 inkAtEnd = uint256(artIn).wdiv(auction_.art).wmul(auction_.ink);@audit div before mul

Multiply before divide

[-] uint256 inkAtEnd = uint256(artIn).wdiv(auction_.art).wmul(auction_.ink); [+] uint256 inkAtEnd = uint256(artIn).wmul(auction_.ink).wdiv(auction_.art);

#0 - HickupHH3

2022-07-18T14:04:23Z

See libraries wdiv and wmul, it'll be doing multiplication then division.

#1 - ecmendenhall

2022-07-19T04:25:04Z

#2 - HickupHH3

2022-07-19T10:29:40Z

IMO it shouldn't be a duplicate; #28 does a much better job at explaining why the rounding error can still occur despite the code doing multiplication first, then division: (artIn * 1e18) / auction_.art * auction_.ink / 1e18.

Edit: Nvm it isn't up to me to decide, should only be giving objective factual comments.

#3 - alcueca

2022-07-21T10:54:04Z

It doesn't matter which finding is better described, they are both invalid.

uint256(artIn).wdiv(auction_.art).wmul(auction_.ink); is equivalent to artIn * 1e18 / auction_.art * auction_.ink / 1e18

#4 - PierrickGT

2022-07-29T10:15:04Z

Agree with sponsor and Hickup, we do multiply first by 1e18 and then divide by 1e18, so it will cancel each other out. For this reason, I have labelled both issues as being invalid.

#5 - dmitriia

2022-08-05T20:28:53Z

Agree with sponsor and Hickup, we do multiply first by 1e18 and then divide by 1e18, so it will cancel each other out. For this reason, I have labelled both issues as being invalid.

It's understood, but this doesn't look to be enough, please kindly read the description of #28

#6 - dmitriia

2022-08-08T15:18:31Z

It doesn't matter which finding is better described, they are both invalid.

uint256(artIn).wdiv(auction_.art).wmul(auction_.ink); is equivalent to artIn * 1e18 / auction_.art * auction_.ink / 1e18

@alcueca The expressions aren't equivalent and there are a range of cases where precision loss leads to value rounding as it is shown in #28. I.e. both findings are valid. The severity is debatable, I believe as 1e18 does cover a substantial chunk of cases (but not all of them as you imply here), so it should be medium. It would be high if the precision was lost in majority of the cases

#7 - HickupHH3

2022-08-08T17:58:26Z

@dmitriia I thought about this, the issue would still persist regardless of order in a different manner.

The fix: artIn * auction_.ink / 1e18 * 1e18 / auction_.art will render zero in cases where the current implementation wouldn't: (artIn * 1e18) / auction_.art * auction_.ink / 1e18. Consider the case where

  • artIn = 1e10
  • auction_.ink = 1e6
  • auction_.art = 1e15

The fix would yield 1e10 * 1e6 / 1e18 * 1e18 / 1e15 = 0 while the current implementation would yield 1e10 * 1e18 / 1e15 * 1e6 / 1e18 = 10.

#28 makes a point of the fyToken amount auction_.art being generally greater than 1e18, which I agree with. However, I think the likelihood of it exceeding 1e36 is very low.

#8 - dmitriia

2022-08-08T18:22:24Z

@HickupHH3 Yes, you are right, the proper fix here is an introduction of additional precision enhancing multiplier, switching wdiv with wmul just reduces the probability of encountering the issue, altering, but not removing the surface.

The issue itself can be formulated as 'using wad math isn't enough to fully counter division precision loss'. The real life probability might be low, but these two issues aren't invalid, just describe a corner case (as many others actually are, which is natural, as main case is usually already thought of)

#9 - PierrickGT

2022-08-08T20:16:54Z

@dmitriia @HickupHH3 thanks for looking into this issue.

@GalloDaSballo wrote a script to compare the two order of operations and noticed that the rounding difference does exist but it's in an order of magnitude of 1 billionth of a ETH (1e9), which is negligible. For this reason, I will remove the invalid label and downgrade this issue to a QA Report one.

The script is available here: https://gist.github.com/GalloDaSballo/1f86b550b45975445848bec61353f45e And here is the result: unknown

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter