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: 33/133
Findings: 4
Award: $330.63
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: horsefacts
Also found by: 0xc0ffEE, IllIllI, Picodes, Sm4rty, berndartmueller, csanuragjain, shenwilly, unforgiven
35.1904 USDC - $35.19
If fillOrder
is called by a contract that expect onERC721Received
to be called when receiving NFT, it could potentially result in irregular state for the receiver contract.
_mint(order.maker, uint256(orderHash)); ... _mint(msg.sender, positionId);
The current implementation uses _mint
instead of _safeMint
. As ERC721 transfers within the contract use the safeTransferFrom
variant, it would be better to keep it consistent and use the safe variant, so as not to confuse contract developers that integrate Putty.
ERC721TokenReceiver
standard after seeing the ERC721.safeTransferFrom
implementation, so she relies on onERC721Received
to update the contract's state when minting the option NFT.withdraw
or exercise
.Add _safeMint
function in PuttyV2Nft.sol
and use it instead of _mint
in fillOrder()
.
#0 - outdoteth
2022-07-06T19:38:31Z
Duplicate: Contracts that canโt handle ERC721 tokens will lose their Putty ERC721 position tokens: https://github.com/code-423n4/2022-06-putty-findings/issues/327
๐ Selected for report: berndartmueller
Also found by: IllIllI, Lambda, TrungOre, auditor0517, hansfriese, sashik_eth, shenwilly
Some ERC20 tokens do not allow zero-value transfer and would revert on transfer. In the current implementation of withdraw
, it's possible for the feeAmount
to return zero but still attempting to transfer, causing users inability to withdraw funds when using such tokens as the baseAsset
.
uint256 feeAmount = 0; if (fee > 0) { feeAmount = (order.strike * fee) / 1000; ERC20(order.baseAsset).safeTransfer(owner(), feeAmount); }
When order.strike * fee
is lower than 1000
, feeAmount
will be 0
.
Put the zero value check on feeAmount
instead of fee
:
uint256 feeAmount = (order.strike * fee) / 1000; if (feeAmount > 0) { ERC20(order.baseAsset).safeTransfer(owner(), feeAmount); }
#0 - outdoteth
2022-07-07T12:48:44Z
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: codexploder
Also found by: ACai, Critical, cccz, horsefacts, ignacio, shenwilly, unforgiven, xiaoming90
110.3615 USDC - $110.36
Judge has assessed an item in Issue #233 as Medium risk. The relevant finding follows:
#0 - HickupHH3
2022-07-16T07:03:14Z
Missing sanity check on duration
Duplicate: Orders with low durations can be easily DOSโd and prevent possibility of exercise: https://github.com/code-423n4/2022-06-putty-findings/issues/265
๐ 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.1306 USDC - $47.13
There is no minimum order.duration
check. A faulty frontend or user mistake could input a very low duration, causing the option to expire near instantly.
This will allow short order takers to receive the premium without taking the risk, as the funds can be withdrawn immediately.
Consider adding a minimum duration check:
require(order.duration >= 3600, "Duration too short");
require(_fee < 30, "fee must be less than 3%");
This check conflicts with the unit test testItCannotSetFeeGreaterThan3Percent
, which tests that fee should not be greater than 3%, instead of lower than 3%.
It's more intuitive to use must not be greater than
check. Consider updating the code to use the inclusive comparison operator instead:
require(_fee <= 30, "fee must not be greater than 3%");
#0 - outdoteth
2022-07-07T18:53:17Z
- Missing sanity check on duration
Duplicate: Orders with low durations can be easily DOSโd and prevent possibility of exercise: https://github.com/code-423n4/2022-06-putty-findings/issues/265