Platform: Code4rena
Start Date: 29/06/2022
Pot Size: $50,000 USDC
Total HM: 20
Participants: 133
Period: 5 days
Judge: hickuphh3
Total Solo HM: 1
Id: 142
League: ETH
Rank: 22/133
Findings: 3
Award: $810.11
π Selected for report: 0
π Solo Findings: 0
π Selected for report: zzzitron
Also found by: Kenshin, Metatron, PwnedNoMore, danb, minhquanym
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L442
in fillOrder
, if the order is short call, it means that msg.sender
is buying a call option the order maker.
in such case, floorAssetTokenIds
must be an empty list.
The problem is that order.floorTokens
is not checked to be an empty list.
Alice signs a short call order of buying a specific crypto punk.
She maliciously sets order.floorTokens
to a list containing BAYC contract's address.
When Bob calls fillOrder
he must set floorAssetTokenIds to an empty list.
Later he tries to exercize the option. his order is the reverse order from Alice's order, meaning it's long call. Therefore, line 442 will run:
_transferFloorsOut(order.floorTokens, positionFloorAssetTokenIds[uint256(orderHash)]);
which will make the transaction revert, because order.floorTokens.length
is 1
and positionFloorAssetTokenIds[uint256(orderHash)].length
is 0
.
change lines 298 to:
require(floorAssetTokenIds.length == 0 && order.floorTokens.length == 0, "Invalid floor tokens length");
#0 - outdoteth
2022-07-06T18:05:40Z
Short call with floorTokens will result in a revert when exercising: https://github.com/code-423n4/2022-06-putty-findings/issues/369
π Selected for report: IllIllI
Also found by: 0x29A, 0xDjango, 0xc0ffEE, AmitN, BowTiedWardens, StErMi, auditor0517, berndartmueller, cccz, danb, dipp, dirk_y, hansfriese, horsefacts, hyh, kirk-baird, oyc_109, peritoflores, rfa, sseefried, swit, xiaoming90, zzzitron
5.5216 USDC - $5.52
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L268
fillOrder
is payable. however, if the order's token is not weth, there is no reason sending eth in the transaction. In such case, the transaction should revert.
in all the branches where eth is not supposed to be sent, add:
require(msg.value == 0);
#0 - outdoteth
2022-07-06T19:27:28Z
Duplicate: Native ETH can be lost if itβs not utilised in exercise and fillOrder: https://github.com/code-423n4/2022-06-putty-findings/issues/226
π Selected for report: xiaoming90
Also found by: 0x1f8b, 0x29A, 0x52, 0xDjango, 0xNazgul, 0xNineDec, 0xSolus, 0xf15ers, 0xsanson, AmitN, Bnke0x0, BowTiedWardens, Chom, David_, ElKu, Funen, GalloDaSballo, GimelSec, Hawkeye, IllIllI, JC, JohnSmith, Kaiziron, Kenshin, Lambda, Limbooo, MadWookie, Metatron, MiloTruck, Nethermind, Picodes, ReyAdmirado, Sneakyninja0129, StErMi, TomJ, Treasure-Seeker, TrungOre, Waze, Yiko, _Adam, __141345__, antonttc, async, aysha, catchup, cccz, cryptphi, csanuragjain, danb, datapunk, defsec, delfin454000, dirk_y, doddle0x, durianSausage, exd0tpy, fatherOfBlocks, gogo, hake, hansfriese, horsefacts, hubble, itsmeSTYJ, joestakey, oyc_109, pedroais, peritoflores, rajatbeladiya, reassor, robee, rokinot, samruna, saneryee, sashik_eth, shenwilly, shung, simon135, sseefried, unforgiven, zer0dot, zzzitron
47.6468 USDC - $47.65
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L526
It's possible to cancel an order at any time, which might cause confusion.
For example, Alice calls fillOrder
and gets an order NFT.
She cancels the order she owns and believes that it's canceled.
However, it didn't change anything.
In cancel
, verify that the order is not registered:
require(!_exists(hashOrder(order));
(_exists
is an ERC721 function)
#0 - outdoteth
2022-07-07T13:59:52Z
Duplicate: Order can be cancelled even if order was already filled: https://github.com/code-423n4/2022-06-putty-findings/issues/396
#1 - HickupHH3
2022-07-11T00:51:34Z
Warden did not submit QA report, this will be the primary.