4

I would like to restrict the number of NFTs any one address can own. How would you implement this in a Solidity smart contract? Say I have an ERC721 NFT contract, Square.sol:

      import "../node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol";
      
      contract Square is ERC721 {
        
        constructor() ERC721("Square", "SQUARE") public {}
        
        string[] public squares;
        mapping (address => uint) public ownerSquareCount;
            
        function mint(string memory _colour) public {
    
          // No one should own more than one square
          require(ownerSquareCount[msg.sender] == 0, 'Each address may only own one square');
          
          squares.push(_colour);
          uint id = squares.length;
          ownerSquareCount[msg.sender]++;
          
          //Open Zeppelin ERC721 _safeMint function
          _safeMint(msg.sender, id);
               
          }
      }

I have tested the above code, but it still allows a single account to mint more than one Square NFT.

(I recognize that anyone can simply create multiple addresses as a work-around, but I'm hoping the effort of having to manage lots of addresses will limit the extent to which this would occur)

EDIT

I have found the solution. For some reason, the ownerSquareCount mapping does not work. Instead, you can use the balanceOf function, which is part of the ERC721 standard. If you change line 10 to:

require(balanceOf(msg.sender) == 0, 'Each address may only own one square');

It works like a charm, throwing an error if an account tries to mint more than one token.

I am only a beginner, but one piece of advice I can share: if you are building smart contracts off a standard (like ERC721 or ERC20), dig deep into those existing contracts. A lot of the functionality you are about to code is probably already done there. I found myself tidying up my NFT smart contract by simply deleting my functions and using the built-in ones.

1
  • 1
    You will also have to modify any other function that changes ownership like transfer, transferFrom.
    – Ismael
    Mar 18, 2021 at 17:02

1 Answer 1

1
contract Square is ERC721 {

    constructor() ERC721("Square", "SQUARE") {}

    string[] public squares;
    mapping (address => uint) public ownerSquareCount;
        
    function mint(string memory _colour) public {
        require(ownerSquareCount[msg.sender] == 0, "You can't mint more than 1 sqaure"); //// difference, solution
        // No one should own more than one square
        require(ownerSquareCount[msg.sender] == 0, 'Each address may only own one square');
        
        squares.push(_colour);
        uint id = squares.length;
        ownerSquareCount[msg.sender]++;
        
        //Open Zeppelin ERC721 _safeMint function
        _safeMint(msg.sender, id);
            
    }

you just need to verify how much squares user have e.g. you just need to put a check at top which allows user to mint, if user haven't minted any nft then it'll allow user to mint.

difference mentioned in code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.