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: 1/133
Findings: 7
Award: $4,724.00
π Selected for report: 0
π Solo Findings: 0
π Selected for report: kirk-baird
Also found by: Lambda, csanuragjain, hansfriese, minhquanym
https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L526-L535 https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L573-L584
A user might have 2 filled orders unexpectedly by canceling an already filled order. Then she might pay the premium 2 times even though she wanted only one order.
Currently, it doesn't check whether the order is filled or not when a user cancels her order. So a user might miss the FilledOrder event and fill another order after canceling the old order.
Solidity Visual Developer of VSCode
We should check whether the order was filled already when canceling an order so that users don't confuse filled and canceled orders. We can modify cancel() like below.
function cancel(Order memory order) public { require(msg.sender == order.maker, "Not your order"); bytes32 orderHash = hashOrder(order); require(ownerOf(uint256(orderHash)) == address(0), "Filled already"); // mark the order as cancelled cancelledOrders[orderHash] = true; emit CancelledOrder(orderHash, order); }
#0 - outdoteth
2022-07-06T18:09:27Z
Duplicate: Itβs possible to fill an order twice by accepting a counter offer for an already filled order: https://github.com/code-423n4/2022-06-putty-findings/issues/44
π Selected for report: hyh
Also found by: hansfriese
An order maker might steal premium from the sender by setting order.strike = 0. It's known that some ERC20 tokens don't allow 0 transfer and it will revert when the order sender tries to exercise his long position. So the order maker will receive back his tokens after the order is expired.
As we can see here, some tokens don't allow 0 transfer. Let's call the token TOK and assume 1 TOK = 1 USDC. And I can't find a restriction on that order.strike must be positive and I think it would be possible to create an order that has a positive premium and zero strikes.
Solidity Visual Developer of VSCode
We should check order.strike != 0 before transfer. Modification for L436.
if(order.strike != 0) { ERC20(order.baseAsset).safeTransferFrom(msg.sender, address(this), order.strike); }
In the fillOrder() function, there are similar transfers here and here, but there will be no loss of funds because the order won't be filled anyway.
#0 - 0xlgtm
2022-07-05T08:29:01Z
#1 - dmitriia
2022-07-06T17:04:50Z
To add a bit here, zero strike options are pretty common and valid derivative type.
#2 - outdoteth
2022-07-07T13:02:28Z
Duplicate: Cannot exercise call contract if strike is 0 and baseAsset reverts on 0 transfers: https://github.com/code-423n4/2022-06-putty-findings/issues/418
π Selected for report: kirk-baird
Also found by: 0xA5DF, Kenshin, cccz, chatch, csanuragjain, hansfriese, hyh, itsmeSTYJ, pedroais, sashik_eth, unforgiven, xiaoming90
An attacker(order maker) might make the sender can't withdraw tokens using vulnerable tokens. So the sender can't receive tokens after strike payment.
I've explained the vulnerable ERC721 token in my high-risk submission. (An order maker might steal premium from the sender by revoking exercise() using a vulnerable asset.)
So it wouldn't be profitable for Alice but Bob won't receive anything after paying 0.9 WETH (strike - premium).
Solidity Visual Developer of VSCode
Same as the high-risk finding, it's difficult to suggest a perfect solution to fix this issue but I think it would be good to add some kind of whitelists for ERC20 and ERC721 that can be used while creating a new order.
#0 - outdoteth
2022-07-07T13:34:37Z
Duplicate: Setting malicious or invalid erc721Assets, erc20Assets or floorTokens prevents the option from being exercised: https://github.com/code-423n4/2022-06-putty-findings/issues/50
π 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/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L338 https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L360 https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L436
Ensure zero msg.value if transferring from user and baseAsset is not WETH. A user that mistakenly calls either fillOrder() or exercise() with native ETH when baseAsset is not WETH, his native ETH will be locked in the contract.
There is a reference of the same issue.
Solidity Visual Developer of VSCode
We should ensure msg.value == 0 for above cases.
} else { require(msg.value == 0, "ETH sent"); ERC20(order.baseAsset).safeTransferFrom(msg.sender, order.maker, order.premium); }
#0 - rotcivegaf
2022-07-04T23:39:55Z
Duplicate of #226
#1 - outdoteth
2022-07-06T19:27:13Z
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: berndartmueller
Also found by: IllIllI, Lambda, TrungOre, auditor0517, hansfriese, sashik_eth, shenwilly
PuttyV2.withdraw() might revert with zero transfer. So users can't withdraw their funds and tokens.
As we can check from previous issue, some ERC20 tokens don't allow transfer of 0 amount. And when we calculate feeAmount, feeAmount might be zero even though the fee is positive when order.strike is less than 1000. Then the fee transfer might revert and users can't withdraw their funds and tokens.
Solidity Visual Developer of VSCode
We can modify this part like below.
uint256 feeAmount = (order.strike * fee) / 1000; if (feeAmount != 0) { ERC20(order.baseAsset).safeTransfer(owner(), feeAmount); }
#0 - outdoteth
2022-07-07T12:49:23Z
Duplicate: withdraw() can be DOSβd for baseAsset ERC20s that prevent 0 transfers if the calculated feeAmount is 0 due to rounding: https://github.com/code-423n4/2022-06-putty-findings/issues/283
π 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.1303 USDC - $47.13
π Selected for report: GalloDaSballo
Also found by: 0v3rf10w, 0x1f8b, 0xA5DF, 0xDjango, 0xHarry, 0xKitsune, 0xNazgul, 0xNineDec, 0xc0ffEE, 0xf15ers, 0xkatana, 0xsanson, ACai, Aymen0909, Bnke0x0, BowTiedWardens, Chom, ElKu, Fitraldys, Funen, Haruxe, Hawkeye, IllIllI, JC, JohnSmith, Kaiziron, Kenshin, Lambda, Limbooo, MadWookie, Metatron, MiloTruck, Picodes, PwnedNoMore, Randyyy, RedOneN, ReyAdmirado, Ruhum, Sm4rty, StErMi, StyxRave, TerrierLover, TomJ, Tomio, UnusualTurtle, Waze, Yiko, _Adam, __141345__, ajtra, ak1, apostle0x01, asutorufos, c3phas, cRat1st0s, catchup, codetilda, cryptphi, datapunk, defsec, delfin454000, durianSausage, exd0tpy, fatherOfBlocks, gogo, grrwahrr, hake, hansfriese, horsefacts, ignacio, jayfromthe13th, joestakey, ladboy233, m_Rassska, mektigboy, minhquanym, mrpathfindr, natzuu, oyc_109, rajatbeladiya, reassor, rfa, robee, rokinot, sach1r0, saian, sashik_eth, simon135, slywaters, swit, z3s, zeesaw, zer0dot
21.1794 USDC - $21.18