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: 24/133
Findings: 3
Award: $727.39
π Selected for report: 0
π Solo Findings: 0
π Selected for report: zishansami
Also found by: 0x52, 0xsanson, auditor0517, berndartmueller, csanuragjain, zzzitron
https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L451 https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L497-L503
Inconsistent charging admin fee for PuttyV2.exercise() and PuttyV2.withdraw(). In exercise(), it doesn't charge admin fee at all, but in withdraw() it charges the fee even when a user receives back his strike amount after order expiration.
I've contacted out.eth with this issue and he said fee must be applied if the order was exercised properly. So in exercise(), we should add a logic to take fee here. And in withdraw(), we shouldn't take a fee when an order isn't exercised here.
Manual Review
uint256 feeAmount = (order.strike * fee) / 1000; if(feeAmount != 0) { ERC20(order.baseAsset).safeTransfer(owner(), feeAmount); } ERC20(order.baseAsset).safeTransfer(msg.sender, order.strike - feeAmount);
uint256 feeAmount = isExercised ? ((order.strike * fee) / 1000) : 0; if (feeAmount != 0) { ERC20(order.baseAsset).safeTransfer(owner(), feeAmount); } ERC20(order.baseAsset).safeTransfer(msg.sender, order.strike - feeAmount);
#0 - outdoteth
2022-07-06T18:24:46Z
Duplicate: Fees are only applied on puts if they are expired: https://github.com/code-423n4/2022-06-putty-findings/issues/269
π 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#L337-L339 https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L359-L361 https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L435-L437
If baseAsset is not WETH and a user calls PuttyV2.fillOrder() or PuttyV2.exercise() with ETH, the ETH will be locked in the contract and he can't receive it back.
This is the link to the same issue.
Manual Review
Recommend checking msg.value == 0 when baseAsset is not WETH.
} else { require(msg.value == 0, "lost ETH"); ERC20(order.baseAsset).safeTransferFrom(msg.sender, order.maker, order.premium); }
#0 - rotcivegaf
2022-07-04T23:36:48Z
Duplicate of #226
#1 - outdoteth
2022-07-06T19:26:36Z
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
A user might fail to withdraw his funds and asset. Such a scenario would happen when the strike amount is small.
Some ERC20 tokens don't allow to transfer 0 amount like this example. And in the below formula, feeAmount might be zero when order.strike is small.
feeAmount = (order.strike * fee) / 1000;
So in this case, a user can't withdraw his funds and assets forever.
Manual Review
Recommend checking feeAmount is not zero before transfer.
#0 - outdoteth
2022-07-07T12:49:12Z
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