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: 13/109
Findings: 3
Award: $2,383.77
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: philogy
Also found by: KIntern_NA, auditor0517, bin2chen, cccz, hansfriese, hyh, ladboy233, m9800, pauliax, pedroais, ronnyx2017, wagmi, wastewa, zzykxx
Users can recover already burned gobblers after minting a legendary gobbler.
The main flaw is that it doesn't reset getApproved[id]
here.
As a result, users can have more emissionMultiple
than they should by recovering the burned gobblers.
The below attack scenario is possible.
Alice
has certain number of gobblers like 50 and she sets getApproved[id] = Alice
for her gobblers here.getApproved[id]
will be remaining here.Alice
transfers already burned NFTs to herself using transferFrom() with from = address(0), to = Alice
.unchecked
block.emissionMultiple
again from the burned tokens here and she will get more GOO tokens.Solidity Visual Developer of VSCode
We should delete getApproved[id]
here.
#0 - csanuragjain
2022-09-27T17:27:21Z
Seems duplicate of https://github.com/code-423n4/2022-09-artgobblers-findings/issues/389
#1 - GalloDaSballo
2022-10-02T14:12:48Z
🌟 Selected for report: zzykxx
Also found by: 8olidity, IllIllI, Lambda, berndartmueller, bytehat, devtooligan, hansfriese, imare, obront, philogy, shung, tonisives, zdhu, zkhorse
ArtGobblers
contract wouldn't receive a random seed forever by a malicious user.
Currently it can't execute revealGobblers()
and upgradeRandProvider()
when gobblerRevealsData.waitingForSeed == true
.
So if the contract fails to receive the random seed after requesting it, waitingForSeed
will be true
forever and the whole logic will be messy because the contract can't reveal new gobblers.
More configuration capability: VRF V1 always waited for 10 blocks on Ethereum before delivering on-chain randomness.
If your fulfillRandomness implementation reverts, the VRF service will not attempt to call it a second time. Make sure your contract logic does not revert. Consider simply storing the randomness and taking more complex follow-on actions in separate contract calls made by you or your users.
ArtGobblers
contract requested a new random seed, gobblerRevealsData.waitingForSeed
will be true permanently and the contract can't reveal NFTs.Solidity Visual Developer of VSCode
I think we should reset gobblerRevealsData.waitingForSeed = false
in upgradeRandProvider() so that the admin can upgrade a RandProvider
when there is a problem with the previous one even though gobblerRevealsData.waitingForSeed == true
.
function upgradeRandProvider(RandProvider newRandProvider) external onlyOwner { gobblerRevealsData.waitingForSeed = false; randProvider = newRandProvider; // Update the randomness provider. emit RandProviderUpgraded(msg.sender, newRandProvider); }
Otherwise, we can add a new function like ResetWaitingForSeed()
to reset gobblerRevealsData.waitingForSeed = false.
function ResetWaitingForSeed() external onlyOwner { gobblerRevealsData.waitingForSeed = false; }
#0 - Shungy
2022-09-27T17:25:47Z
<del>requestRandomSeed()
can be called again after a day of wait, regardless if the waitingForSeed
is true or not.
I don't think this is a death sentence. I guess DOS can be sustained for a while by a group with sufficient funds, but it would be too costly. Not sure if it warrants a High risk, but there is definitely some Med risk issue trusting the randomness provider that it will eventually call acceptRandomSeed()
. I saw an issue with this design as well, and described it in a similar if not duplicate finding: https://github.com/code-423n4/2022-09-artgobblers-findings/issues/279</del>
Edit: Just realized requestRandomSeed
cannot be re-requested until toBeRevealed
is consumed: https://github.com/code-423n4/2022-09-artgobblers/blob/2ae644ace932271fb34399c1c0771aabae2e423c/src/ArtGobblers.sol#L517
This makes my previous paragraph mostly wrong. And it actually makes this submission stand out from the other submissions about reveals getting halted. Because this submission shows a very probably route on how this can happen. A well-funded malicious party could do it.
#1 - GalloDaSballo
2022-09-29T21:29:42Z
#2 - hansfriese
2022-09-30T05:19:38Z
@GalloDaSballo, can I ask one thing with this issue if you don't mind?
I think #153 shows it wouldn't work properly when the randProvider
stops working.
But this issue shows it won't work by a malicious user even if the randProvider
is normal.
I am wondering if these issues should be considered as duplicates.
#3 - GalloDaSballo
2022-09-30T22:07:10Z
@GalloDaSballo, can I ask one thing with this issue if you don't mind? I think #153 shows it wouldn't work properly when the
randProvider
stops working. But this issue shows it won't work by a malicious user even if therandProvider
is normal. I am wondering if these issues should be considered as duplicates.
Have added a note to check again
After thinking about it twice am not convinced that it is reasonable to expect that an attacker could deny a tx for 10 blocks in a row, also I'll need to look into why the VRF would drop the TX vs it just being stuck in the mempool.
I will re-check it though to give it the benefit of the the doubt
🌟 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
ArtGobblers
and GobblerReserve
contracts inherite the Owned
contract and use setOwner()
function without any two-phase ownership transfers.
Each event should use three indexed fields if there are three or more fields
#0 - GalloDaSballo
2022-10-06T19:19:40Z
NC
L
I disagree with the event indexed without an explanation
1L 1NC