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: 14/133
Findings: 3
Award: $1,317.61
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: berndartmueller
227.0813 USDC - $227.08
Fees is calculated and sent only in the condition if put is expired or call is exercised No fees sent in either withdraw() or exercise() in condition if put is exercised or call is expired.
Loss of fees
Calculate similar fees and send
#0 - outdoteth
2022-07-06T18:25:01Z
Duplicate: Fees are only applied on puts if they are expired: https://github.com/code-423n4/2022-06-putty-findings/issues/269
#1 - HickupHH3
2022-07-11T03:11:20Z
dup of #285
🌟 Selected for report: hubble
1038.3233 USDC - $1,038.32
The solidity version 0.8.13 has below two issues applicable to PuttyV2
Vulnerability related to ABI-encoding. ref : https://blog.soliditylang.org/2022/05/18/solidity-0.8.14-release-announcement/ This vulnerability can be misused since the function hashOrder() and hashOppositeOrder() has applicable conditions. "...pass a nested array directly to another external function call or use abi.encode on it."
Vulnerability related to 'Optimizer Bug Regarding Memory Side Effects of Inline Assembly' ref : https://blog.soliditylang.org/2022/06/15/solidity-0.8.15-release-announcement/ PuttyV2 inherits solidity contracts from openzeppelin and solmate, and both these uses inline assembly, and optimization is enabled while compiling.
Use recent Solidity version 0.8.15 which has the fix for these issues
#0 - outdoteth
2022-07-06T19:34:21Z
great catch.
#1 - outdoteth
2022-07-08T13:34:07Z
Report: Use of solidity 0.8.13 with known issues in ABI encoding and memory side effects
#2 - outdoteth
2022-07-15T10:34:29Z
PR with fix: https://github.com/outdoteth/putty-v2/pull/6
🌟 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
52.2103 USDC - $52.21
The PuttyV2 contract will hold good amount of TVL (Weth, ERC20's and ERC721's balances).
In case of any eventuality, there may be a requirement to freeze some of the operations of the protocol. Hence a pause and unpause mechanism will help during that period.
Incorporate or import the relevant library to pause/unpause few external functions.
In the function exercise(),
line#401 require(block.timestamp < positionExpirations[uint256(orderHash)], "Position has expired"); The check for positionExpirations should ideally include the block.timestamp as an edge case.
The reason is that in withdraw() function, the block.timestamp is exclusive
line#481 require(block.timestamp > positionExpirations[longPositionId] || isExercised, "Must be exercised or expired");
line#401 require(block.timestamp <= positionExpirations[uint256(orderHash)], "Position has expired");
In the function fillOrder(),
line#290 require(block.timestamp < order.expiration, "Order has expired"); The check for order.expiration should ideally include the block.timestamp as an edge case.
line#290 require(block.timestamp <= order.expiration, "Order has expired");
In PuttyV2.sol the PuttyV2 contract inherits Ownable, which has the function renounceOwnership() If by mistake or maliciously the renounceOwnership() is called, there is a possibility of losing control on the PuttyV2 contract.
Override this renounceOwnership() function in PuttyV2.sol by making it a no-op.
In PuttyV2.sol the PuttyV2 contract inherits Ownable, which has the function transferOwnership() which only checks for null address. If by mistake a wrong address is used in transferOwnership(), then there is a possibility of losing control on the PuttyV2 contract.
Best practice is to use two step process to transfer ownership 1st Step : setNewOwner << setting/proposing the address of the new Owner 2nd Step : acceptOwnership << the new Owner will execute this function to complete the ownership transfer
In fillOrder() , the return value during transfer of premium to order.maker is not checked when weth is used.
line#336 IWETH(weth).transfer(order.maker, msg.value);
In case of any failure in this line, the fillOrder will still succeed.
Store the return value and check if success.