Platform: Code4rena
Start Date: 30/10/2023
Pot Size: $49,250 USDC
Total HM: 14
Participants: 243
Period: 14 days
Judge: 0xsomeone
Id: 302
League: ETH
Rank: 86/243
Findings: 1
Award: $27.69
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: MrPotatoMagic
Also found by: 3th, Fulum, JohnnyTime, K42, Kose, SAAJ, Toshii, catellatech, cats, clara, digitizeworx, dimulski, dy, glcanvas, hunter_w3b, ihtishamsudo, niki, peanuts
27.6948 USDC - $27.69
Analysis Overview
NextGen is a suite of smart contracts for launching generative art NFT projects on Ethereum. It consists of a core ERC721 token contract, a minter contract for handling phased minting logic, admin contracts for access control, and various randomizer contracts.
Architecture
NextGen follows a modular architecture by splitting functionality across multiple focused contracts:
Benefits of Modular Architecture
Separation of concerns - Each contract has a single responsibility making the logic easier to understand.
Flexibility - Components can be upgraded independently. For example, a new Randomizer contract can be deployed and integrated without changing any other logic.
Reduce risk surface - Issues with one contract are contained, and do not impact other components.
Avoid "God" contract - A single giant contract that does everything is hard to maintain and secure.
Interactions Between Contracts
The core contracts interact with each other as follows:
This is coordinated via interfaces like INextGenCore
without tight coupling between contracts.
Downsides of Modular Design
There's a complexity cost for managing interactions between all the contracts and stitching together functionality across them.
Proper integration testing across contracts is critical to ensure correct end-to-end behavior.
The modular architecture maximizes flexibility, upgradability, and separation of concern - best practices for complex dApps.
Access Control
Access control is handled by the NextGenAdmin contract which manages admin roles. There are 3 levels of access control:
This allows fine-grained control over permissions. The owner of NextGenAdmins serves as the root admin.
Implementation
These roles are implemented using address mappings and modifiers:
// Global admin addresses mapping(address => bool) public globalAdmins; // Collection admin permissions mapping(address => mapping(uint256 => bool)) public collectionAdmins; // Function admin permissions mapping(address => mapping(bytes4 => bool)) public functionAdmins; // Modifier checks global admin modifier GlobalAdminRequired() { require(globalAdmins[msg.sender], "Not global admin"); _; } // Modifier checks collection admin modifier CollectionAdminRequired(uint256 collectionId) { require(collectionAdmins[msg.sender][collectionId], "Not collection admin"); _; } // Modifier checks function admin modifier FunctionAdminRequired(bytes4 funcSelector) { require(functionAdmins[msg.sender][funcSelector], "Not function admin"); _; }
Privileges
Each role has privileges suitable to its scope:
Deploying Admins
The NextGenAdmin owner serves as the root admin. They can add the initial set of global admins, who can then further delegate roles.
Careful assignment of the root admin is critical to avoid granting unintended access.
Potential risks:
Randomness
NextGen has 3 randomizer contracts for generating a random hash or "seed" for each token's art generation. This ensures each token gets unique art.
Relying on Chainlink and ARRNG provides strong randomness but has dependencies. The custom RandomizerNXT provides a fallback with on-chain data.
NextGen uses a modular approach with 3 randomizer contracts:
Using Multiple Sources
The rationale for having 3 implementations is:
The admin can configure which randomizer a collection uses.
Potential Issues
Proper configuration and failover procedures are important to leverage the benefits while mitigating the risks.
Potential risks:
Minting Logic
The MinterContract handles all the minting logic including phased allowlist minting, merkle proofs, various pricing models etc. This keeps the core ERC721 contract lightweight.
All the complex minting logic is handled by the NextGenMinter contract including:
This keeps NextGenCore simple as the standard ERC721 implementation.
Benefits
Separating minting logic provides:
Potential Issues
Proper test coverage across minting variants is critical. The allowlist logic needs robust protections against bypassing limits.
Potential risks:
On-chain Data
NextGen stores metadata and art generation scripts fully on-chain for decentralization. There is an option to freeze collections when done.
This provides full decentralization - the artwork can be reconstructed just from the blockchain.
Freezing Collections
Once a collection is complete, the admin can freeze it permanently. This prevents any future changes.
Freezing happens by flipping a collectionFreeze
boolean to true for that collection.
Benefits
Potential Issues
Proper implementation of freezing is critical to delivering on the promises of an immutable collection.
Potential risks:
Recommendations
Use a timelock mechanism like DAOhaus for delaying/approving critical admin functions to mitigate malicious or accidental use.
Consider slashing conditions around VRF/RNG oracle manipulation if feasible.
Formal verification of key functions like allowlist minting would provide highest assurance.
The main risks stem from centralized admin access and complexity around minting logic. Proper access controls for admin functions is critical.
29 hours
#0 - c4-pre-sort
2023-11-27T14:36:31Z
141345 marked the issue as insufficient quality report
#1 - c4-judge
2023-12-07T16:51:27Z
alex-ppg marked the issue as grade-b