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: 76/173
Findings: 2
Award: $28.53
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: CodingNameKiki
Also found by: 0x1f8b, 0x4non, 0x5rings, 0xAgro, 0xMirce, 0xRobocop, 0xSmartContract, 0xackermann, AkshaySrivastav, ArmedGoose, Aymen0909, BClabs, Breeje, Dewaxindo, Diana, HollaDieWaldfee, IceBear, IllIllI, Iurii3, Josiah, Krayt, PaludoX0, Phenomana, PrasadLak, RaymondFam, Rolezn, SaeedAlipoor01988, SaharDevep, SleepingBugs, adriro, arialblack14, bin2chen, brevis, btk, carlitox477, carrotsmuggler, catellatech, chaduke, chrisdior4, cryptonue, cryptostellar5, csanuragjain, ddimitrov22, fellows, glcanvas, halden, hl_, horsefacts, jat, joestakey, kenta, libratus, lukris02, luxartvinsec, manikantanynala97, martin, matrix_0wl, nadin, nicobevi, oberon, peanuts, prestoncodes, rbserver, sakshamguruji, sashik_eth, sayan, seeu, thekmj, tnevler, trustindistrust, tsvetanovv, xAriextz, zadaru13, zaskoh
17.196 USDC - $17.20
Avoid floating pragmas for non-library contracts.
While floating pragmas make sense for libraries to allow them to be included with multiple different versions of applications, it may be a security risk for application implementations.
A known vulnerable compiler version may accidentally be selected or security tools might fall-back to an older compiler version ending up checking a different EVM compilation that is ultimately deployed on the blockchain.
It is recommended to pin to a concrete compiler version.
Issue Information: [L001]
quest-protocol\contracts\Erc1155Quest.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\Erc20Quest.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\Quest.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\QuestFactory.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\RabbitHoleReceipt.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\RabbitHoleTickets.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\ReceiptRenderer.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\TicketRenderer.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\interfaces\IQuest.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\interfaces\IQuestFactory.sol::2 => pragma solidity ^0.8.15; quest-protocol\contracts\test\SampleErc1155.sol::2 => pragma solidity ^0.8.15;
Issue Information: [NC-001] - Functions Mutating Storage Should Emit Events
Functions mutating storage should emit an Event for easy off-chain monitoring.
quest-protocol\contracts\Erc1155Quest.sol::41 => function _transferRewards(uint256 amount_); quest-protocol\contracts\Erc1155Quest.sol::102 => function withdrawFee() public onlyAdminWithdrawAfterEnd; quest-protocol\contracts\Erc1155Quest.sol::33 => function start() public override;
Issue Information: [QA-001] - transferOwnership should be two step process
"QuestFactory.sol" inherit OpenZeppelin's OwnableUpgradeable contract which enables the onlyOwner role to transfer ownership to another address. It's possible that the onlyOwner role mistakenly transfers ownership to the wrong address, resulting in a loss of the onlyOwner role. The current ownership transfer process involves the current owner calling newQuest.transferOwnership(msg.sender) If the nominated EOA account is not a valid account, it is entirely possible the owner may accidentally transfer ownership to an uncontrolled account, breaking all functions with the onlyOwner() modifier. Lack of two-step procedure for critical operations leaves them error-prone if the address is incorrect, the new address will take on the functionality of the new role immediately
for Example : -Alice deploys a new version of the whitehack group address. When she invokes the whitehack group address setter to replace the address, she accidentally enters the wrong address. The new address now has access to the role immediately and is too late to revert
The contract have many onlyOwner function and the contract is inherited from the Ownable which includes transferOwnership. Recommended Mitigation Steps Implement zero address check and Consider implementing a two step process where the owner nominates an account and the nominated account needs to call an acceptOwnership() function for the transfer of ownership to fully succeed. This ensures the nominated EOA account is a valid and active account.
#0 - c4-sponsor
2023-02-07T23:05:55Z
waynehoover marked the issue as sponsor confirmed
#1 - c4-judge
2023-02-15T22:06:49Z
kirk-baird marked the issue as grade-b
๐ Selected for report: IllIllI
Also found by: 0x1f8b, 0x4non, 0xAgro, 0xSmartContract, 0xhacksmithh, 0xngndev, Aymen0909, Bnke0x0, Breeje, Deivitto, Diana, Dug, Iurii3, LethL, MiniGlome, NoamYakov, RaymondFam, ReyAdmirado, Rolezn, SAAJ, adriro, ali, arialblack14, atharvasama, c3phas, carlitox477, catellatech, chaduke, cryptonue, cryptostellar5, ddimitrov22, dharma09, doublesharp, favelanky, georgits, glcanvas, gzeon, halden, horsefacts, jasonxiale, joestakey, karanctf, lukris02, matrix_0wl, nadin, navinavu, saneryee, shark, thekmj
11.3269 USDC - $11.33
Issue Information: [G001]
quest-protocol\contracts\Quest.sol::103 => uint256 redeemableTokenCount = 0; quest-protocol\contracts\RabbitHoleReceipt.sol::115 => uint foundTokens = 0; quest-protocol\contracts\RabbitHoleReceipt.sol::126 => uint filterTokensIndexTracker = 0;
Issue Information: [G002]
quest-protocol\contracts\RabbitHoleReceipt.sol::129 => if (tokenIdsForQuest[i] > 0) {
Issue Information: [G003]
quest-protocol\contracts\QuestFactory.sol::17 => bytes32 public constant CREATE_QUEST_ROLE = keccak256('CREATE_QUEST_ROLE'); quest-protocol\contracts\QuestFactory.sol::211 => bytes32 messageDigest = keccak256(abi.encodePacked('\x19Ethereum Signed Message:\n32', hash_));
Issue Information: [G004]
quest-protocol\contracts\Quest.sol::2 => function _setClaimed(uint256[] memory tokenIds_);
In Solidity 0.8+, thereโs a default overflow check on unsigned integers. Itโs possible to uncheck this in for-loops and save some gas at each iteration, but at the cost of some code readability, as this uncheck cannot be made inline.
Issue Information: [G005]
quest-protocol\contracts\Quest.sol::70 => for (uint i = 0; i < tokenIds_.length; i++); quest-protocol\contracts\Quest.sol::104 => for (uint i = 0; i < tokens.length; i++); quest-protocol\contracts\RabbitHoleReceipt.sol::117 => for (uint i = 0; i < msgSenderBalance; i++); quest-protocol\contracts\RabbitHoleReceipt.sol::128 => for (uint i = 0; i < msgSenderBalance; i++);
for (uint i = 0; i < tokenIds_.length; i++) {.....}
for (uint i = 0; i < tokenIds_.length;) { // ... unchecked { ++i; } }
#0 - c4-judge
2023-02-15T22:11:01Z
kirk-baird marked the issue as grade-b