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: 44/133
Findings: 3
Award: $118.54
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Picodes
Also found by: 0xNineDec, 0xsanson, Metatron, antonttc, berndartmueller, catchup, dirk_y, sseefried, unforgiven
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L240
Admin can update the fee by calling setFee() function. Such changes may effect user decisions, hence they should have some safeguards such as timelocks. This way users can have the necessary time to update their decisions.
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L240
Manual review
A timelock can be added for such critical changes which may effect user decisions.
#0 - outdoteth
2022-07-06T18:35:27Z
Duplicate: Admin can change fee at any time for existing orders: https://github.com/code-423n4/2022-06-putty-findings/issues/422
🌟 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.238 USDC - $47.24
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L526-L535
cancel() function does not check if the order has already been filled. A maker can cancel the order even if it was filled, thinking he cancelled the order when actually he did not. If the maker is short, long counterparty can exercise the position at a later time and short maker would find himself in an unexpected situation.
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L526-L535
Manual review
I suggest to check the value of positionExpirations of the order. If it is non-zero and not expired, that means position is filled and not expired yet. In such a case, revert the cancellation operation informing the user that he can't cancel a filled order.
#0 - outdoteth
2022-07-07T13:59:40Z
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:50:26Z
Warden did not submit QA report, this will be the primary.
🌟 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.1707 USDC - $21.17
For loop index increments can be made unchecked for solidity versions > 0.8.0. There is no risk of overflowing the index of the for loops.
10 instances: https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L556 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L594 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L611 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L627 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L637 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L647 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L658 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L670 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L728 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L742
I suggest to change the original code from this
for (uint256 i = 0; i < whitelist.length; i++) { if (target == whitelist[i]) return true; }
to this:
for (uint256 i; i < whitelist.length; ) { if (target == whitelist[i]) return true; unchecked { ++i; } }
Prefix increment/decrements (++i) is about 5 gas cheaper than postfix increment/decrements (i++). The reason of this is i++ stores the value of i initially and than increments, meaning an additional memory location is required for the operation.
10 instances: https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L556 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L594 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L611 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L627 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L637 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L647 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L658 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L670 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L728 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L742
There is no need the initialise uint to 0, bool to false, address to address(0), since they default to these values. It uses extra 8 gas to init stack variables.
11 instances: https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L497 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L556 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L594 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L611 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L627 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L637 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L647 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L658 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L670 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L728 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L742
fee is accessed twice in withdraw function; on lines L498 and L499. It can be cached and used from stack to save an SLOAD, which would save ~97 gas.
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L498-L499
Using public visibility for constants would cause getter function creations for them which would cause unnecessary gas usage.
https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L89 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L95 https://github.com/code-423n4/2022-06-putty/blob/main/contracts/src/PuttyV2.sol#L101