2

I'm working with an app where different users can create their own ERC721 tokens by passing token, symbol total supply etc. Currently, the code is creating the token, but it has common name only.

pragma solidity ^0.5.0;

import "./token/ERC721/ERC721Full.sol";
import "./drafts/Counters.sol"; 


contract MyContract is ERC721Full {

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor() ERC721Full("MYToken", "MYT") public {          
    }

    function mint(address player) public returns (uint256) {

        _tokenIds.increment();

        uint256 newItemId = _tokenIds.current();
        _mint(player, newItemId);
        return newItemId;
    }
}

How to create tokens with different name and symbol for each user? and mint to their account?

Do I need to deploy a smart contract per user? if so, the complexity will be increased by time. And is there any best practice available.

3
  • I would suggest write a contract which creates ERC721 contracts for the users - users simply enter the required information. Or do this in your backend so your backend deploys a contract for the user. Apr 3, 2020 at 9:43
  • Thanks @LauriPeltonen, any good example for contract which creates ERC721 contracts ?
    – Div
    Apr 3, 2020 at 10:04
  • sorry, no. maybe mr. Google can find some Apr 3, 2020 at 10:09

4 Answers 4

3

I solved it this way.

BTW, this code has no guards against stopping a user from registering multiple coins.

// SPDX-License-Identifier: Unlicense                                                                                                                                                                               
pragma solidity >0.8.5;

import "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "node_modules/@openzeppelin/contracts/utils/Counters.sol";

contract MyContract {

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    mapping(uint    => ERC721) contracts;
    mapping(address =>   uint) lastContractIds;

    function myLastTokenId(address player) public view returns (uint256) {
        return lastContractIds[player];
    }

    function mint(address player, string memory sym, string memory desc) public returns (uint256) {
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
        contracts[newItemId] = new ERC721(sym, desc);
        lastContractIds[player] = newItemId;
        return newItemId;
    }

}
2

You can use a clone factory smart contract to do so. https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol

An example of your ERC721 factory would be

pragma solidity ^0.6.0;
import "./clone_factory.sol";
import "./erc721.sol";


contract ERC721Factory is cloneFactory {
    address  payable template;


    constructor(address payable _templateAddress) public {
        template = _templateAddress;
    }

    function create(string memory myName, string memory mySymbol)
    external returns (address) {
        address payable _address = payable(createClone(template));
        ERC721(_address).set(msg.sender, myName, mySymbol);
        return _address;
    }
}

template will be the address of your ERC721 contract.

The new _address will be the address of new ERC721 token with the myName and mySymbol. The owner of new ERC721 token will be msg.sender. You can pass more variable to set function as per your requirements.

Your constructor function of the ERC721 contract should ideally be empty and should have a set function that will set myName and mySymbol.

1
  • Thanks, I'll give a try and let you know.
    – Div
    Apr 6, 2020 at 6:26
1

Here is the full contract that worked for me:

pragma solidity ^0.5.0;

import "./ERC721Full.sol";
import "./Counters.sol";     

contract MyContract is ERC721Full {

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor(string memory myName, string memory mySymbol) ERC721Full(myName, mySymbol) public {

    }

    function mint(address player, uint totalSupply) public returns (bool) {

        for(uint256 i = 1; i<= totalSupply; i++){
            _tokenIds.increment();
            uint256 newItemId = _tokenIds.current();
            _mint(player, newItemId);
        }
    }
}

contract ContractFactory {

    address[] public contracts;
    address public lastContractAddress;       

    function getContractCount() public view returns(uint contractCount) {
        return contracts.length;
    }

     // deploy a new purchase contract
    function deploy(string memory name, string memory symbol) public returns(address newContract){
         MyContract c = new MyContract(name,symbol);
         address cAddr = address(c);
         contracts.push(cAddr);
         lastContractAddress = cAddr;

         return cAddr;
    }        
    function mint(MyContract tokenAddress, uint256 totalSupply) public {

      tokenAddress.mint(msg.sender, totalSupply);
    }       
}
0

You can pass the strings to the constructor instead hardcoding them (if I understood your question correctly).

pragma solidity ^0.5.0;

import "./token/ERC721/ERC721Full.sol";
import "./drafts/Counters.sol"; 


contract MyContract is ERC721Full {

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor(string myName, string mySymbol) ERC721Full(myName, mySymbol) public {          
    }

    function mint(address player) public returns (uint256) {

        _tokenIds.increment();

        uint256 newItemId = _tokenIds.current();
        _mint(player, newItemId);
        return newItemId;
    }
}`

2
  • I'm sorry if the question is not cleared. The constructor will be called only once, then the name of that tokens will be same. Do I need to deploy new contract for each user?
    – Div
    Apr 3, 2020 at 8:30
  • Ok - I misunderstood the question. Apr 3, 2020 at 8:53

Your Answer

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

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