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

Security review · April 2023

Marketplace

for NFTR

NFTR engaged Guardian to review the security of its NFT name marketplace. From the 1st of April to the 8th of April, a team of 2 auditors reviewed the source code in scope.

Published
Review window
April 1 to 8, 2023
Language
Solidity
Chains
Ethereum
Sector
NFTs
  • 2 Critical
  • 2 High
  • 4 Medium
  • 4 Low
  • 0 Informational

12 resolved

Scope

Overview

NFTR engaged Guardian to review the security of its NFT name marketplace. From the 1st of April to the 8th of April, a team of 2 auditors reviewed the source code in scope.

Findings 12

  1. NFTR-1 Critical Two Names For One Token Logical Error Resolved
    Location
    NFTRegistry.sol: 273

    Description

    Names could be transferred to an NFT with an existing name but the tokenByName mapping still contains the overwritten name pointing to the NFT. As a result, two different names may point to the same NFT.

    Consider the following scenario:

    1. Alice owns an NFT with name “Alice”
    2. Bob owns an NFT with name “Bob”
    3. Name “Alice” is transferred to Bob’s NFT
    4. tokenByName is updated to reflect that “Alice” points to Bob’s NFT.
    5. tokenByName still has an entry for name “Bob” also pointing to Bob’s NFT.
    6. It now appears that Bob is now the owner of both names “Bob” and “Alice”.
    7. A user purchases name “Bob” but ends up receiving name “Alice” upon transfer.

    Recommendation

    If a name may be transferred to an NFT with an existing name, dereserve the old name using releaseTokenByName.

  2. NMKT-1 Critical No Bids Can Be Entered Logical Error Resolved
    Location
    NameMarketplace.sol: 376

    Description

    Initially, when no bids have been entered, the existing bid will have default values – address(0) as the collection and 0 for the tokenId. The zero address does not have function ownerOf, so the call to getOwner will revert. As a result, no bids can be entered.

    Recommendation

    Bypass the ownership check when there are no existing bids.

  3. NMKT-2 High Overwriting Previous Name Unexpected Behavior Resolved
    Location
    NameMarketplace.sol

    Description

    When a bid is accepted through acceptBidForName or an offered name is purchased through buyName, there is no check that the NFT the name shall be transferred to is already named. As a result, a user may unexpectedly lose their old name upon transfer.

    Recommendation

    Consider if owned names should be overwritten upon transfer. If necessary, clearly document such behavior.

  4. NMKT-3 High Griefing Name Sellers Griefing Resolved
    Location
    NameMarketplace.sol

    Description

    It is simple for a malicious actor to grief a seller by placing a bid higher than the previous and then withdrawing the bid or transferring the tokenTo to another address. As a result, any bids made with true buying intention are lost and the seller is unable to sell his name.

    Recommendation

    Consider allowing for a few blocks to pass before the bid can be overwritten so that a malicious actor risks losing the funds sent to make the ineffectual bid.

  5. NMKT-4 Medium Inaccurate Event Data Events Resolved
    Location
    NameMarketplace.sol: 262

    Description

    string memory name = toLower(nftr.tokenName(collectionFrom, tokenFrom))

    is performed after the transfer is already made. As a result, the event doesn’t emit the name that has been transferred but the empty string.

    Recommendation

    Grab the name from the toToken or cache the name prior to transfer.

  6. NMKT-5 Medium Inconsistent Encoded Names Logical Error Resolved
    Location
    NameMarketplace.sol

    Description

    There may be potential issues stemming from name parameters being lowered when getting the NFT with the provided name, but the encodedName being produced from a non-parsed input.

    Consider the following scenario:

    1. Bob owns an NFT with name “DIGITAL”
    2. Alice calls enterBidForName and passes “digital” for the name parameter.
    3. Bob calls acceptBidForName with name “DIGITAL”, but the encoded name does not match the encoded name generated by Alice’s “digital”.
    4. Bob’s transaction reverts and is unable to accept Alice’s bid.

    Recommendation

    Lower the inputted name prior to encoding.

  7. NMKT-6 Medium Reset Offers on Fee Change Logical Error Resolved
    Location
    NameMarketplace.sol: 327

    Description

    If the owner changes the feePerc, even if they lower it, all offers with a different fee will need to be reset due to a fee mismatch. A seller would prefer a lower fee so it is unexpected for their offer to be rendered invalid.

    Recommendation

    Compare the offer’s fee percentage against an upper bound rather than an exact check.

    .

  8. NMKT-7 Medium Unable To Withdraw Bid Unexpected Behavior Resolved
    Location
    NameMarketplace.sol: 427

    Description

    There is potential for a user to be unable to withdraw their bid.

    Consider the following scenario:

    1. Bob bids for the name “Alice”.
    2. He then receives the NFT named “Alice” through secondary markets or a direct transfer.
    3. Bob is unable to withdraw his bid value because he now owns the NFT named “Alice”.

    Recommendation

    Consider whether it is necessary to check for ownership when withdrawing a bid for a name.

    If necessary, properly document such behavior for users.

    .

  9. NMKT-8 Low Unnecessary Casting Best Practices Resolved
    Location
    NameMarketplace.sol: 157

    Description

    _WETH is already an address so it is unnecessary to cast it to one.

    Recommendation

    Remove address(_WETH) cast.

  10. NMKT-9 Low Using delete Best Practices Resolved
    Location
    NameMarketplace.sol

    Description

    delete on a mapping entry can be used to reset to defaults rather than setting a zeroed off Offer/Bid.

    Recommendation

    Consider using delete if only default values are necessary.

  11. NMKT-10 Low Improper Visibility Best Practices Resolved
    Location
    NameMarketplace.sol

    Description

    toLower has visibility public but it under the internal functions section.

    Recommendation

    Consider marking the function with visibility internal or move it to a different section.

  12. NMKT-11 Low Loop Optimization Optimization Resolved
    Location
    NameMarketplace.sol

    Description

    The length of bStr can be cached. Furthermore, because a name’s length is restricted in NFTR, the index can be incremented in a unchecked block.

    Recommendation

    Consider the above gas optimizations.

More from NFTR

  1. Naming Credits

    18 findings 18 findings: 1 medium, 17 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