Closed code423n4 closed 2 years ago
The warden does not explain how finalize() may be called multiple times, when it is expected that the state will change to finalize following the finalize() call.
0xean marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2022-11-size/blob/79aa9c01987e57a760521acecfe81b28eab3b313/src/SizeSealed.sol#L327 https://github.com/code-423n4/2022-11-size/blob/79aa9c01987e57a760521acecfe81b28eab3b313/src/SizeSealed.sol#L318-L322
Vulnerability details
Impact
Bidders' fund will be stolen by malicious seller, they can not get refund.
Proof of Concept
In
finalize()
,FinalizeData memory data
is local, which means in each call,data
is re-initialized. By callingfinalize()
multiple times, a malicious seller can get thefilledQuote
multiple times until all the bid funds are drained.Even worse, if combined with another vector, by manipulating
bidIndices[]
at the end, none of the base token will be transferred since theif (quotePerBase < data.reserveQuotePerBase)
will continue the loop. The seller can get all the base token back.The steps are as following:
each call to
finalize()
will receivefilledQuote
. // src/SizeSealed.soladditionally, to get base token back at last. Call
finalize()
filled with low bids or fake empty bids, so all the bids will be unsuccessful byif (quotePerBase < data.reserveQuotePerBase) continue;
. And all the base token will be considered unsold and returned to the seller.Noted that the key point of this vulnerability is
finalize()
could be called multiple times, the seller can exploit it. Even without step 2, the seller can still drain the fund. Step 2 is another vector, only make it worse.Tools Used
Manual analysis.
Recommended Mitigation Steps
rule to call
finalize()
:finalize()
FinalizeData data
a storage variableSanity check for
bidIndices[]
:bidIndices[]
by bid pricebidIndices[]
, only use internal generated sortedbidIndices[]
. When create the bid, the array can be sorted in time.revert
for the case of ascending order