Platform: Code4rena
Start Date: 13/12/2022
Pot Size: $36,500 USDC
Total HM: 5
Participants: 77
Period: 3 days
Judge: gzeon
Total Solo HM: 1
Id: 191
League: ETH
Rank: 55/77
Findings: 1
Award: $25.95
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: c3phas
Also found by: 0x1f8b, Aymen0909, Bnke0x0, Bobface, IllIllI, PaludoX0, Rahoz, RaymondFam, ReyAdmirado, Rolezn, Sathish9098, adriro, chaduke, codeislight, ctrlc03, indijanc, izhelyazkov, kuldeep, nadin, neko_nyaa, nicobevi, rvierdiiev, shark
25.9485 USDC - $25.95
Gas optimizations:
VRFNFTRandomDraw.sol
- the variables don't get instantiated in the constructor, thus have no need to be immutable. Constant variables are cheaper.Settings
struct in interfaces/IVRFNFTRandomDraw.sol
can be re-ordered to pack the token
and subscriptionId
variable into a single slot, because token
is an address
type - 160 bits, and subscriptionId
is of uint64
type - 64 bits, their total is 224 bits, which is less than the EVM word size of 256 bits. So, packing them together will save a potential cold read / write.CurrentRequest
struct in interfaces/IVRFNFTRandomDraw.sol
can be changed to pack hasChosenRandomNumber
and drawTimelock
in a single slot, again potentially saving additional reads/writes gas cost. This can be done by reducing the number of bits drawTimelock
takes - since the drawTimelock
represents a timestamp, it can be safely represented in a uint64
type (which accounts for a max timestamp in the next 550 years) or a uint72
type (which can account for max time of the next 150k years). Additionally, currentChosenTokenId
in the same struct can be reduced to uint176
type or even less, accounting for the maximum token ids which can be chosen in a given collection (usually less than 10 000 NFTs are in most collections). With smart packing of the variables relative to their maximum values, it may be possible to pack all of the variables into the struct in a single slot.msg.sender
in makeNewDraw
function in VRFNFTRandomDrawFactory.sol
or winnerClaimNFT
function in VRFNFTRandomDraw.sol
- will be more expensive than using msg.sender
directly - using msg.sender
costs 2 gas, while caching it in a variable costs 3 gas to push in on the stack.transfer
/ safeTransfer
can be used in lastResortTimelockOwnerClaimNFT
and winnerClaimNFT
function in VRFNFTRandomDraw.sol
instead of transferFrom
to save on gas.#0 - c4-judge
2022-12-17T17:40:16Z
gzeon-c4 marked the issue as grade-b