SIZE contest - cryptphi's results

An on-chain sealed bid auction protocol.

General Information

Platform: Code4rena

Start Date: 04/11/2022

Pot Size: $42,500 USDC

Total HM: 9

Participants: 88

Period: 4 days

Judge: 0xean

Total Solo HM: 2

Id: 180

League: ETH

SIZE

Findings Distribution

Researcher Performance

Rank: 55/88

Findings: 1

Award: $38.28

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: Trust

Also found by: 8olidity, HE1M, JTJabba, KIntern_NA, KingNFT, M4TZ1P, Picodes, PwnedNoMore, R2, V_B, bin2chen, cryptonue, cryptphi, fs0c, hansfriese

Awards

38.2759 USDC - $38.28

Labels

bug
3 (High Risk)
partial-25
upgraded by judge
edited-by-warden
duplicate-252

External Links

Lines of code

https://github.com/code-423n4/2022-11-size/blob/main/src/SizeSealed.sol#L415-L440 https://github.com/code-423n4/2022-11-size/blob/main/src/SizeSealed.sol#L238

Vulnerability details

Impact

The SizeSealed contract's cancelBid() function can be called after auction has been finalized, thereby allowing the bidder to withdraw their quoteToken after bid is finalized

This is possible by bypassing the if (a.data.lowestQuote != type(uint128).max || block.timestamp <= a.timings.endTimestamp + 24 hours) statement by allowing a.data.lowestQuote to be set to type(uint128).max during the finalize() call where clearingQuote and clearingBase are user controlled, as well as making the cancelBid and finalize call after 24 hours the auction ended.

With the control of these arguments in the clearing price calculation during finalize(), the bidder can manipulate the final data.previousQuotePerBase value by using a different address to place the last bid such that the bid's quoteAmount would pass all checks.

With all this inputs provided, it would be possible for a bidder to finalize the auction and then call cancelBid() to receive back the quoteTokens deposited for the auction.

Proof of Concept

  1. Alice bids for an auction
  2. Just before the end of the bid, Alice places the last bid using another address with a crafted bid quiteAmount.
  3. 24 hours just after auction ends (i.e block.timestamp == a.timings.endtimeT,imestamp +24 hours), Alice calls finalize() with user supplied input for clearingQuote set to type(uint128).max and clearingBase set to an appropriate number.
  4. Where no overflow reverts occur, finalize() is completed successfully with Alice receiving the calculated amount of quoteTokens for the auction.
  5. Alice then calls cancelBid() right away.
  6. Since the a.data.lowestQuote is set to type(uint128).max and the time is 24hrs after auction ended , the if-statement is bypassed and Alice receives back the quoteToken she deposited for the auction.

Tools Used

Manual review

Apply a logic that checks the Auction State, the atState modifier could be applied to ensure the auction is in the AcceptingBids state for the call.

#0 - trust1995

2022-11-09T00:24:25Z

Warden spotted the correct issue, but did not POC an attack flow like the other submissions, therefore I believe it to be invalid. Specifically, they did not show a way to make finalize succeed whilst setting clearingQuote to type(uint128).max Dup of #252

#1 - c4-judge

2022-11-09T15:04:46Z

0xean marked the issue as duplicate

#2 - c4-judge

2022-11-09T16:02:07Z

0xean marked the issue as partial-25

#3 - c4-judge

2022-12-06T00:27:19Z

0xean changed the severity to 3 (High Risk)

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