SIZE contest - KIntern_NA'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: 27/88

Findings: 2

Award: $158.70

🌟 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

153.1035 USDC - $153.10

Labels

bug
3 (High Risk)
satisfactory
duplicate-252

External Links

Lines of code

https://github.com/code-423n4/2022-11-size/blob/main/src/SizeSealed.sol#L33-L36 https://github.com/code-423n4/2022-11-size/blob/main/src/SizeSealed.sol#L217 https://github.com/code-423n4/2022-11-size/blob/main/src/SizeSealed.sol#L238 https://github.com/code-423n4/2022-11-size/blob/main/src/SizeSealed.sol#L297

Vulnerability details

Vulnerable details

  • In contract, an auction's state will beStates.Finalized if data.lowestQuote of this auction is different from type(uint128).max. L33-34
  • data.lowestQuote is assigned to equal clearingQuote when seller finalize auction. (L238) This value will be checked by the last data.previousQuotePerBase (L297-L299):
if (data.previousQuotePerBase != FixedPointMathLib.mulDivDown(clearingQuote, type(uint128).max, clearingBase)) {
    revert InvalidCalldata();
}
  • Let call lastQuoteAmount and lastBaseAmount is quoteToken and baseToken amount of last filled bid -> data.previousQuotePerBase = FixedPointMathLib.mulDivDown(lastQuoteAmountt, type(uint128).max, lastBaseAmount); It means clearingQuote * type(uint128).max / clearingBase must equal to lastQuoteAmount * type(uint128).max / lastBaseAmount => If clearingQuote is type(uint128).max, it can still pass the check if the ratio clearingQuote / clearingBase is equal to lastQuoteAmount / lastBaseAmount Example: clearingQuote = clearingBase = type(uint128).max, and lastQuoteAmount / lastBaseAmount= 1
  • This vulnerable leads that seller can finalize auction with clearingQuote = type(uint128).max, but auction's state will still be States.RevealPeriod because data.lowestQuote still be type(uint128).max. It allows seller repeat finalize again or cancel auction to steal many quote tokens and base tokens from contract.

Impact

When lastQuoteAmount, lastBaseAmount of auction are satisfied, seller can finalize auction without updating state to State.Finalized by passing clearingQuote = type(uint128).max. Worse than that, sellers can modify last bids for large auctions (by using other addresses to bid) and exploit this vulnerable (repeat finalize many times without updating state or cancel auction, steal many tokens of contract).

Proof of Concept

https://gist.github.com/huuducst/d3e496680e6091e417d65bfcec17b77f You can place this file into /src/test folder and run it using:

forge test --match-test testFinalizeIssue -vv

Tools Used

VS Code Foundry

Should revert if seller finalize with clearingQuote == type(uint128).max (function finalize)

if (clearingQuote == type(uint128).max) {
    revert InvalidCalldata();
}

#0 - trust1995

2022-11-08T23:50:08Z

Good find, dup of #252

#1 - c4-judge

2022-11-09T15:01:05Z

0xean marked the issue as duplicate

#2 - c4-judge

2022-12-06T00:22:30Z

0xean marked the issue as satisfactory

Awards

5.604 USDC - $5.60

Labels

bug
2 (Med Risk)
satisfactory
duplicate-237

External Links

Lines of code

https://github.com/code-423n4/2022-11-size/blob/main/src/SizeSealed.sol#L157-L159

Vulnerability details

Impact

Because contract did not limit number of bids for each address at 1 auction, attacker can bid many times (same auction) in 1 transaction. If it makes bids.length increase up to 1000, and other bidders can not bid at this auction.

Proof of Concept

Contract just limit 1000 number of bids at 1 auction. See in this condition in function bid():

if (bidIndex >= 1000) {
    revert InvalidState();
}

And contract has no limit of the number of bids for each bidder at 1 auction. So attacker can easily bid up to 1000 times in 1 transaction and prevent bidding from others.

Tools Used

VS Code

Limit number of bids for each bidder at 1 auction or remove limitation of 1000 bids.

#0 - trust1995

2022-11-08T23:48:11Z

This is not considered a DOS as attacker is basically executing 1000 legitimate trades with the seller, as intended. Report does not specify any interesting quirks to make the DOS do any harm to the auction.

#1 - c4-judge

2022-11-09T15:38:07Z

0xean marked the issue as duplicate

#2 - c4-judge

2022-12-06T00:22:29Z

0xean marked the issue as satisfactory

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