Platform: Code4rena
Start Date: 20/09/2022
Pot Size: $100,000 USDC
Total HM: 4
Participants: 109
Period: 7 days
Judge: GalloDaSballo
Id: 163
League: ETH
Rank: 33/109
Findings: 2
Award: $525.56
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: zzykxx
Also found by: 8olidity, IllIllI, Lambda, berndartmueller, bytehat, devtooligan, hansfriese, imare, obront, philogy, shung, tonisives, zdhu, zkhorse
470.3582 USDC - $470.36
https://github.com/code-423n4/2022-09-artgobblers/blob/main/src/ArtGobblers.sol#L509-L538
ArtGobblers incorporates Chainlink VRF v1 which uses off-chain, centralized processes to choose a random number which is then verified on-chain. ArtGobblers also contains a permissioned upgradeRandProvider()
which can be used to change the rand provider contract. However, the upgrade cannot be called while waiting for a random seed (after calling requestRandomSeed()
but before fulfillRandomness()
has been called).
If upgradeRandProvider
were called with the wrong address and subsequently requestRandomSeed()
was called, or if a problem with Chainlink VRF v1 were to arise that prevented Chainlink from calling fullfillRandomness()
while waiting for the random seed, then the reveal process could be irrecoverably bricked. upgradeRandProvider
cannot save us because of the check:
if (gobblerRevealsData.waitingForSeed) revert SeedPending();
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept. https://github.com/code-423n4/2022-09-artgobblers/blob/main/src/ArtGobblers.sol#L560-L567
Consider adding an additional bool arg to upgradeRandProvider()
which would reset waitingForSeed
to false and toBeRevealed
to zero. This would allow for optionally (and explicitly) resetting the waiting state of the contract and prevent it from being permanently bricked.
@@ -557,9 +560,14 @@ contract ArtGobblers is GobblersERC721, LogisticVRGDA, Owned, ERC1155TokenReceiv /// @notice Upgrade the rand provider contract. Useful if current VRF is sunset. /// @param newRandProvider The new randomness provider contract address. - function upgradeRandProvider(RandProvider newRandProvider) external onlyOwner { + function upgradeRandProvider(RandProvider newRandProvider, bool resetWaiting) external onlyOwner { + if (resetWaiting) { + gobblerRevealsData.waitingForSeed = false; + gobblerRevealsData.toBeRevealed = 0; + } +
#0 - Shungy
2022-09-28T16:04:56Z
#1 - GalloDaSballo
2022-09-29T21:30:26Z
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x4non, 0x52, 0x5rings, 0xNazgul, 0xRobocop, 0xSmartContract, 0xdeadbeef, 0xsanson, 8olidity, Amithuddar, Aymen0909, B2, B353N, CertoraInc, Ch_301, Chom, CodingNameKiki, Deivitto, ElKu, Funen, JC, JohnnyTime, Kresh, Lambda, Noah3o6, RaymondFam, ReyAdmirado, RockingMiles, Rolezn, Sm4rty, SuldaanBeegsi, Tadashi, TomJ, Tomio, V_B, Waze, __141345__, a12jmx, ak1, arcoun, asutorufos, aviggiano, berndartmueller, bharg4v, bin2chen, brgltd, bulej93, c3phas, catchup, cccz, ch0bu, cryptonue, cryptphi, csanuragjain, delfin454000, devtooligan, djxploit, durianSausage, eighty, erictee, exd0tpy, fatherOfBlocks, giovannidisiena, hansfriese, ignacio, joestakey, ladboy233, lukris02, m9800, malinariy, martin, minhtrng, obront, oyc_109, pedr02b2, pedroais, pfapostol, philogy, prasantgupta52, rbserver, ronnyx2017, rotcivegaf, rvierdiiev, sach1r0, shung, simon135, throttle, tnevler, tonisives, wagmi, yixxas, zkhorse, zzykxx, zzzitron
55.1985 USDC - $55.20
Severity: Low
In requestRandomBytes()
in ChainlinkV1RandProvider.sol, requestId
is set as the return variable. It is then used (before being assigned a value) to emit the RandomBytesRequested
event. On the following line, an explicit return is used.
/// @notice Request random bytes from Chainlink VRF. Can only by called by the ArtGobblers contract. function requestRandomBytes() external returns (bytes32 requestId) { // The caller must be the ArtGobblers contract, revert otherwise. if (msg.sender != address(artGobblers)) revert NotGobblers(); emit RandomBytesRequested(requestId); // Will revert if we don't have enough LINK to afford the request. return requestRandomness(chainlinkKeyHash, chainlinkFee); }
Impact
An incorrect event is emitted and logged permanently.
Recommendation: Fix it
@@ -63,10 +63,9 @@ contract ChainlinkV1RandProvider is RandProvider, VRFConsumerBase { // The caller must be the ArtGobblers contract, revert otherwise. if (msg.sender != address(artGobblers)) revert NotGobblers(); - emit RandomBytesRequested(requestId); - // Will revert if we don't have enough LINK to afford the request. - return requestRandomness(chainlinkKeyHash, chainlinkFee); + emit RandomBytesRequested(requestId = requestRandomness(chainlinkKeyHash, chainlinkFee)); + }
mintReservedGobblers
for an annoying DoS attackSeverity: Low
mintReservedGobblers() is a non-permissioned external function that can be called by anyone. If the function were called with 0, it would complete successfully, including a emitting an event at the end.
Impact This would mostly just be annoying. If front end was listening to this event, it could possibly have an effect. It would clutter up the recent events and event log queries.
Recommendation:
@@ -836,7 +828,9 @@ contract ArtGobblers is GobblersERC721, LogisticVRGDA, Owned, ERC1155TokenReceiv /// the supply of goo minted gobblers and the supply of gobblers minted to reserves. function mintReservedGobblers(uint256 numGobblersEach) external returns (uint256 lastMintedGobblerId) { + require(numGobblersEach > 0, "CAN'T MINT ZERO");
Severity: Low
foundry.toml has the compiler set to 0.8.13.
Solidity versions 0.8.15 - 0.8.17 fix several bugs introduced in earlier versions of Solidity, 2 of which were introduced in 0.8.13.
Impact
None of the fixed bugs were deemed to directly effect the ArtGobblers contracts.
Recommendation:
It is recommended to upgrade to the latest version of Solidity, or else take a more conservative approach and use an older version such as 0.8.4 which includes many needed features (but possibly less optimizations), but has been around longer and can be deemed more stable.
#0 - GalloDaSballo
2022-10-06T19:11:50Z
R because while it's incorrect it's informational
R as it results in events, no additional side effect
NC
2R 1NC
#1 - GalloDaSballo
2022-10-06T19:12:07Z
Good intentions but missing some additional findings