Platform: Code4rena
Start Date: 31/01/2023
Pot Size: $36,500 CANTO
Total HM: 5
Participants: 38
Period: 3 days
Judge: berndartmueller
Total Solo HM: 2
Id: 212
League: ETH
Rank: 21/38
Findings: 2
Award: $72.33
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: HardlyDifficult
Also found by: 0xAgro, 0xSmartContract, Aymen0909, DevABDee, JC, Matin, Rolezn, SleepingBugs, adriro, brevis, btk, chaduke, d3e4, enckrish, hihen, joestakey, libratus, merlin, nicobevi, rotcivegaf, shark, sorrynotsorry
149.2473 CANTO - $44.97
The add
function in CidNFT.sol takes in an argument called _key
. _key
is only used in the add
function if _type == AssociationType.ORDERED
. To prevent possible user errors when calling the add
function, consider adding a require statement forcing _key
to be empty if _type != AssociationType.ORDERED
.
For better style and less computation consider replacing any power of 10 exponentiation (10**3
) with its equivalent scientific notation (1e3
). For code clarity it is understood why 100 * 10**18
is used. This issue is specifically about the 10**18
.
/src/SubprotocolRegistry.sol
17: uint256 public constant REGISTER_FEE = 100 * 10**18;
Suggested Change
17: uint256 public constant REGISTER_FEE = 100 * 1e18;
The Solidity Style Guide suggests the following function order: constructor, receive function (if exists), fallback function (if exists), external, public, internal, private.
The following contracts are not compliant (examples are only to prove the functions are out of order NOT a full description):
Lines with greater length than 120 characters are used. The Solidity Style Guide suggests that all lines should be 120 characters or less in width.
The following lines are longer than 120 characters, it is suggested to shorten these lines:
/src/CidNFT.sol
/src/SubprotocolRegistry.sol
Some functions use named returns and others do not. It is best for code clearity to keep a consistent style.
returns(uint256 foo)
): AddressRegistry.sol.returns(uint256)
): SubprotocolRegistry.sol.There are some spelling mistakes throughout the codebase. Consider fixing all spelling mistakes.
/src/CidNFT.sol
non-existent
is misspelled as non-existing
.non-existent
is misspelled as non-existant
.subprotocol
is misspelled as subprotocl
(1).subprotocol
is misspelled as subprotocl
(2).The core functions of the codebase (add
and remove
of CidNFT.sol) are bulky and relatively hard to read as a result. Consider breaking the functions up into sub-functions (perhaps by association type).
Permissionless software implies that anyone of any background that has access may use the system. Consider using as broad of language as possible when talking about users. Even if most are, probabilistically, not all users will be male.
/src/CidNFT.sol
_mint(msg.sender, ++numMinted); // We do not use _safeMint here on purpose. If a contract calls this method, he expects to get an NFT back
When registering a new subprotocol in register
of SubprotocolRegistry.sol the max value is not checked. Although the function will revert if _fee
exceeds the size of a uint96
, no proper error message will trigger. Consider adding an error message to better indicate the max fee size.
At the start of CidNFT.sol most comments do not have a trailing .
(ex) unless followed by another sentence (ex). Consider sticking to the original style. The following cases void the original style:
/src/CidNFT.sol
.
: L69, L162, L185, L234, L235, L258, L294, L306, L318..
: L145, L146, L161./src/SubprotocolRegistry.sol
/src/AddressRegistry.sol
#0 - c4-judge
2023-02-18T12:57:45Z
berndartmueller marked the issue as grade-b
🌟 Selected for report: HardlyDifficult
Also found by: 0xAgro, 0xSmartContract, 0xackermann, Aymen0909, Dravee, Matin, MiniGlome, NoamYakov, ReyAdmirado, Rolezn, Ruhum, c3phas, descharre, joestakey
90.8172 CANTO - $27.36
Error checks should revert as early as possible to prevent unnecessary computation.
/src/CidNFT.sol
_nftIDToAdd == 0
is checked. _nftIDToAdd
is a parameter and therefore can be checked at the very beginning of add
./src/SubprotocolRegistry.sol
!(_ordered || _primary || _active)
is checked. All three variables are parameters and therefore can be checked at the very beginning of register
.!ERC721(_nftAddress).supportsInterface(type(CidSubprotocolNFT).interfaceId)
is checked. _nftAddress
is a parameter and therefore can be checked at the very beginning of register
(please consider possible security ramifications).L88 can be converted to an AND statement and transformed as follows to save gas:
From
88: if (!(_ordered || _primary || _active)) revert NoTypeSpecified(_name);
To
if (!_ordered) { if (!_primary) { if (!_active) revert NoTypeSpecified(_name); } }
A uint256
iterator will not overflow before the check variable overflows. Unchecking the iterator increment saves gas.
Example
//From for (uint256 i; i < len; ++i) { //Do Something } //To for (uint256 i; i < len;) { //Do Something unchecked { ++i; } }
/src/CidNFT.sol
150: for (uint256 i = 0; i < _addList.length; ++i) {
#0 - c4-judge
2023-02-18T12:42:38Z
berndartmueller marked the issue as grade-b