Skip to content
$1,000,000 in security audit grants are live now, Apply here →

Security review · October 2022

Naming Credits

for NFTR

After a line by line manual analysis and automated review, Guardian has concluded that:

Published
Language
Solidity
Chains
Ethereum
Sector
NFTs
  • 0 Critical
  • 0 High
  • 1 Medium
  • 17 Low
  • 0 Informational

15 resolved · 3 acknowledged

Scope

Overview

After a line by line manual analysis and automated review, Guardian has concluded that:

  • NFTR’s smart contracts have a LOW RISK SEVERITY
  • NFTR’s smart contracts have an ACTIVE OWNERSHIP
  • Important owner/tempAdmin privileges – updateProtocolFeeRecipient, shutOffAssignments, reduceNamingCredits, setRNMAddress, shutOffFeeRecipientUpdates, addAssignerCredits, nullAssignerCredits, shutOffAssignerAssignments, transferTempAdmin
  • NFTR’s smart contract owner has multiple “write” privileges. Centralization risk correlated to the active ownership is LOW

Findings 18

  1. NMC-1 Low Centralization Risk Centralization / Privilege Resolved
    Location
    NamingCredits.sol

    Description

    tempAdmin has the ability to essentially mint unlimited naming credits (further discussed on NMC-2), as well as control over numerous functions which could negatively affect the rest of the protocol: setRNMAddress, shutOffFeeRecipientUpdates, addAssignerCredits, nullAssignerCredits, shutOffAssignerAssignments, transferTempAdmin.

    Recommendation

    Ensure tempAdmin is a multi-sig.

    Resolution

    NFTR Team: - tempAdmin will be a multi-sig.

  2. NMC-2 Medium Weak Tokenomics Protection Tokenomics / Privilege Resolved
    Location
    NamingCredits.sol

    Description

    The MAX_ASSIGNER_CREDITS and MAX_CREDITS_ASSIGNED offer little to no protection for the protocol tokenomics.

    The MAX_ASSIGNER_CREDITS can be easily circumvented by simply calling the addAssignerCredits multiple times.

    The MAX_CREDITS_ASSIGNED can be easily circumvented by calling the assignNamingCredits function multiple times or calling assignNamingCreditsBulk with a user list that contains the same address multiple times.

    Therefore it is relatively easy for the tempAdmin and assigners to manipulate the tokenomics of the project, potentially creating unlimited naming credits or allowing a particular address to accumulate more than the intended amount of naming credits.

    Recommendation

    Base the MAX_ASSIGNER_CREDITS and MAX_CREDITS_ASSIGNED on the assigner/user balance and possibly introduce a hard cap on the number of namingCredits that can be in circulation to prevent an unexpected amount of namingCredits being created.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  3. NMC-3 Low Zero Address Checks Best Practices Resolved
    Location
    NamingCredits.sol: 64, 78, 88, 101

    Description

    The constructor, transferTempAdmin, and updateProtocolFeeRecipient functions all assign important address contract variables without ensuring any of them are not the zero address.

    Recommendation

    Evaluate whether or not each of these addresses can be assigned to the zero/dead address and add prohibiting requires statements accordingly.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  4. NMC-4 Low Superfluous Code Optimization Resolved
    Location
    NamingCredits.sol: 123

    Description

    The currencyQuantity parameter is required to be equal to numberOfCredits * nftrAddress.namingPriceEther() in the BuyWithEth.YES case, and equal to numberOfCredits * nftrAddress.namingPriceRNM() in the BuyWithEth.NO case.

    Therefore all subsequent computations of numberOfCredits * nftrAddress.namingPriceEther() or numberOfCredits * nftrAddress.namingPriceRNM() can be replaced with the currencyQuantity.

    Recommendation

    Implement the above simplifications.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  5. NMC-5 Low Superfluous Code Optimization Resolved
    Location
    NamingCredits.sol: 123

    Description

    In buyNamingCredits, the require statements inside of the first if statement can be moved into the if statement below. This way the buyWithEth type can be checked just once.

    Recommendation

    Implement the above simplifications.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  6. NMC-6 Low Unnecessary Require Statements Optimization Acknowledged
    Location
    NamingCredits.sol: 138, 200, 258

    Description

    There are several require statements that appear directly before a transferFrom function call or -= operator that would otherwise revert without the presence of the require statement.

    Recommendation

    Remove the unnecessary require statements and optionally replace each -= with a .sub alternative if the revert messages are necessary.

    Resolution

    NFTR Team: - Acknowledged, but left as is for simplicity.

  7. NMC-7 Low Unnecessary Casting Optimization Resolved
    Location
    NamingCredits.sol

    Description

    The nftrAddress and rnmAddress variables are stored as INFTRegistry and IRNM types in the contract, however they are often redundantly cast to INFTRegistry and IRNM types in the buyNamingCredits function.

    Recommendation

    Remove the redundant casts.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  8. NMC-8 Low Typo Typo Resolved
    Location
    NamingCredits.sol: 120

    Description

    On line 120, “buy” is misspelled as “by”.

    Recommendation

    Replace “by” with “buy” in the comment.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  9. NMC-9 Low Default Value Assignment Optimization Resolved
    Location
    NamingCredits.sol: 195

    Description

    On line 195 the uint variable i is initialized to the default value of 0.

    Recommendation

    Remove the unnecessary assignment.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  10. NMC-10 Low Cache Array Length Optimization Resolved
    Location
    NamingCredits.sol: 195

    Description

    Caching the array length outside a for loop saves reading it on each iteration.

    Recommendation

    Declare a len variable and use it as the upper bound in the for loop.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  11. NMC-11 Low Uint Comparisons Optimization Resolved
    Location
    NamingCredits.sol: 191

    Description

    When dealing with unsigned integer types, comparisons with != 0 are cheaper than with > 0.

    Recommendation

    Replace the assigners[msg.sender] > 0 check with assigners[msg.sender] != 0.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  12. NMC-12 Low Storage Modifiers Optimization Resolved
    Location
    NamingCredits.sol: 189

    Description

    In assignNamingCreditsBulk the address[] memory user and address[] memory numberOfCredits parameters are never altered and therefore can be declared calldata.

    Recommendation

    Declare the variables calldata.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  13. NMC-13 Low Shorten Revert Strings Optimization Acknowledged
    Location
    NamingCredits.sol

    Description

    Throughout the contract revert strings that are longer than 32 bytes are used.

    Recommendation

    Shorten revert strings to less than 32 bytes to save on gas.

    Resolution

    NFTR Team: - Acknowledged, but left as is for simplicity.

  14. NMC-14 Low Access Modifiers Optimization Resolved
    Location
    NamingCredits.sol

    Description

    Throughout the contract there are several require statements that assert the msg.sender is the tempAdmin. These require statements can be deduplicated into a single onlyTempAdmin modifier that can be used on each of these functions.

    Recommendation

    Create an onlyTempAdmin modifier and apply it to each of these functions.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  15. NMC-15 Low Duplicate Reads Optimization Resolved
    Location
    NamingCredits.sol

    Description

    In assignNamingCreditsBulk the numberOfCredits[i] value is read up to five times upon each iteration. Declare a uint creditNum outside of the for loop and cache the numberOfCredits value in it upon each iteration.

    Recommendation

    Implement the above suggestion.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  16. NMC-16 Low For-Loop Increment Optimization Resolved
    Location
    NamingCredits.sol: 196

    Description

    Because the user array’s length is bound by MAX_BULK_ASSIGNMENT, there is no risk of overflow. To reduce bytecode, use an unchecked block in the loop to increment.

    Recommendation

    Implement the above suggestion.

    Resolution

    NFTR Team: - The suggested changes were implemented.

  17. NMC-17 Low Custom Reverts Optimization Acknowledged
    Location
    NamingCredits.sol

    Description

    Since Solidity v0.8.4, the more gas-efficient custom-errors have been introduced. They allow for passing dynamic data in the error and remove costly and repeated string error messages.

    Recommendation

    Consider replacing require statements with custom errors.

    https://blog.soliditylang.org/2021/04/21/custom-errors/

    Resolution

    NFTR Team: - Acknowledged, but left as is for simplicity.

  18. NMC-18 Low Visibility Modifiers Visibility Modifiers Resolved
    Location
    NamingCredits.sol: 88, 101

    Description

    The functions setRNMAddress and updateProtocolFeeRecipient are declared as public but are never called from within the contract.

    Recommendation

    Modify the visibility from public to external.

    Resolution

    NFTR Team: - The suggested changes were implemented.

More from NFTR

  1. Marketplace

    12 findings2 critical · 2 high 12 findings: 2 critical, 2 high, 4 medium, 4 low
  2. Protocol Review

    11 findings 11 findings: 4 medium, 7 low

Put your code through the same review.

This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.

Get a quote