Platform: Code4rena
Start Date: 17/03/2023
Pot Size: $36,500 USDC
Total HM: 10
Participants: 98
Period: 3 days
Judge: leastwood
Total Solo HM: 5
Id: 223
League: ETH
Rank: 61/98
Findings: 1
Award: $22.77
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Sathish9098
Also found by: 0xAgro, 0xSmartContract, 0xdaydream, 0xnev, Awesome, Aymen0909, BRONZEDISC, Bauchibred, Deathstore, Diana, IceBear, Jerry0x, Kresh, Matin, Rolezn, Stryder, T1MOH, Udsen, adriro, alejandrocovrr, atharvasama, codeslide, cryptonue, descharre, igingu, jack, joestakey, libratus, lukris02, luxartvinsec, nadin, nasri136, reassor, scokaf, shark, slvDev, tnevler
22.7749 USDC - $22.77
Solmate's Owned
contract used for Namespace
and Tray
doesn't implement two-step ownership transfer.
https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol#L39
function transferOwnership(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnershipTransferred(msg.sender, newOwner); }
Wrongly specified newOwner
will lead to severe consequences, therefore introducing a two-step process should be considered.
In the events BioAdded
and NamespaceFused
there are string type properties marked as indexed
.
event BioAdded(address indexed minter, uint256 indexed nftID, string indexed bio); event NamespaceFused(address indexed fuser, uint256 indexed namespaceId, string indexed name);
String is a reference type. Marking it with indexed
means that a hash of the value will be logged to the topic, while the strings themselves will not be searchable or retrievable from events. It is better to remove indexed
so that the string value is stored in the data field.
Some UTF-8 characters take more bytes than others.
// We check the length in bytes, so will be higher for UTF-8 characters. But sufficient for this check if (bytes(_bio).length == 0 || bytes(_bio).length > 200) revert InvalidBioLength(bytes(_bio).length);
Authors ackonwledge this issue but don't explain the reasoning for not fixing it. Character length can be determined using stringutils
library or a custom implementation.
Namespace burn
function doesn't delete nftCharacters mapping entry for the given NFT. This causes unnecessary bloat for Canto chain
function burn(uint256 _id) external { address nftOwner = ownerOf(_id); if (nftOwner != msg.sender && getApproved[_id] != msg.sender && !isApprovedForAll[nftOwner][msg.sender]) revert CallerNotAllowedToBurn(); string memory associatedName = tokenToName[_id]; delete tokenToName[_id]; delete nameToToken[associatedName]; _burn(_id); }
Code in Utils.sol
is quite complex with a lot of branching. At the same time, code coverage is poor.
Lines coverage: 29.5%
Small changes in this codebase can introduce bugs. Consider adding more tests for uncovered code.
Current implementation of tray generation is pseudorandom. This can lead to a situation where the rarest symbols are minted by those who have more resources for front-running and ahead-of-time calculations. Knowing results in advance can also prevent users from minting, resulting in less fees for the protocol.
True randomness based on oracles can generate more engagement for the protocol.
#0 - c4-judge
2023-04-11T05:43:28Z
0xleastwood marked the issue as grade-b