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: 17/77
Findings: 2
Award: $155.98
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Trust
Also found by: Apocalypto, Madalad, Matin, aga7hokakological, evan, kaliberpoziomka8552, mookimgo, poirots, subtle77, wagmi, yixxas
110.2711 USDC - $110.27
https://github.com/code-423n4/2022-12-forgeries/blob/main/src/VRFNFTRandomDraw.sol#L33
In VRFNFTRandomDraw
, we have that
uint256 immutable MONTH_IN_SECONDS = (3600 * 24 * 7) * 30;
however that calculation is actually 30 weeks, not 30 days. The correct calculation is:
uint256 immutable MONTH_IN_SECONDS = (3600 * 24) * 30;
This means that certain waiting periods may actually be 7 times as long as advertised. For example, users may have to wait as long as 7 months in between draws as opposed to 1 month, and an admin may have to wait 7 years as opposed to 1 year to retreive their target NFT from the contract.
Use solidity constants hours
, days
for time calculations to avoid such calculation mistakes, and to improve code readability.
uint256 immutable MONTH_IN_SECONDS = 30 days;
#0 - c4-judge
2022-12-17T12:53:17Z
gzeon-c4 marked the issue as duplicate of #273
#1 - c4-judge
2022-12-17T12:53:54Z
gzeon-c4 marked the issue as satisfactory
45.7078 USDC - $45.71
There are two instances of comments which contradict the code. Either the comment or the code ought to be updated:
VRFNFTRandomDraw:initialize()
comment states that the size of the drawing range must be "at least two" (>=2
), but the require statement uses a strict inequality which actually enforces "at least three" (>2
)
VRFNFTRandomDraw:lastResortTimelockOwnerClaimNFT()
comment contains "If recoverTimelock is not setup, or if not yet occurred"
, however due to initialize()
logic it is impossible that it would not be setup
NFTs that do not adhere to the ERC721 standard will not be usable in VRFNFTRandomDraw
, as the IERC721EnumerableUpgradeable
interface is used when interacting with the NFT contract. While non-ERC721 NFTs are rare, it is worth noting since CryptoPunks were mentioned as an example drawing NFT in the contest overview/README.
Instead of manually calculating seconds, use the build in keywords minutes
, hours
and days
. This reduces margin for error and improves readability (the calculation for MONTH_IN_SECONDS
is actually incorrect by a factor of 7).
Version
is intended to keep track of implementation versions. However it is possible to upgrade to a new implementation with a version that is less than or equal to the old version. Strictly increasing versions should be enforced for each proxy.
A floating pragma risks a different compiler version being used in production vs testing, which poses security risks.
<br>constant
instead of immutable
For immutable variables whose value is set outside of the constructor, the constant
keyword ought to be used instead to save gas and improve readability.
safeTransferFrom
instead of transferFrom
Concerning ERC721 tokens, transferFrom
can result in tokens being lost if they are sent to a contract that does not implement IERC721Receiver.onERC721Received
. OpenZeppelin encourages the use of safeTransferFrom
over transferFrom
for this reason.
public
or private
#0 - c4-judge
2022-12-17T17:07:14Z
gzeon-c4 marked the issue as grade-b
#1 - gzeoneth
2022-12-17T17:07:39Z
Possible dupe of #108