How to create an upgradeable ERC721?

wuichen asked on GitHub (https://github.com/OpenZeppelin/openzeppelin-contracts-ethereum-package/issues/77)

trying to use erc721full from this package but cannot initialize it correctly. the compiler is telling me that the constructor shouldnt have any arguments. error gets thrown at here. everything works when i switch the library to the original onezeppelin/contracts library

:computer: Environment
im using zepkit from the site.

:1234: Code to reproduce bug

import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Enumerable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/ERC721Enumerable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/IERC721Metadata.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/ERC721Metadata.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/ERC721Full.sol"
contract Thing is ERC721Full, ERC721MetadataMintable, ERC721Burnable, Ownable {
using SafeMath for uint256;
struct Price {
uint256 tokenId;
uint256 price;
string metaId;
TokenState state;
}

mapping(uint256 => Price) public items;
constructor(
   string memory name,
   string memory symbol,
   string memory uri,
   address payable fee,
   address payable creator
) public ERC721Full(name, symbol) {
   maker = creator;
   feeAddress = fee;
   baseUri = uri;
   id = 0;
   transferOwnership(creator);
   _addMinter(creator);

}}

As you are using OpenZeppelin Contracts Ethereum Package I assume that you want to create an upgradeable contract.

For upgradeable contracts, we can’t use constructors and need to use initializers (see
Initialization documentation). This is the reason that there is an issue.

An example of an upgradeable ERC721 is below

:warning: The contract below has not been tested nor audited

Simple721Token.sol

pragma solidity ^0.5.0;

import "@openzeppelin/upgrades/contracts/Initializable.sol";

import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/ERC721Full.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC721/ERC721Mintable.sol";

contract Simple721Token is Initializable, ERC721Full, ERC721Mintable {

    function initialize(address sender) public initializer {
        ERC721.initialize();
        ERC721Metadata.initialize("Simple721Token", "721");
        ERC721Enumerable.initialize();
        ERC721Mintable.initialize(sender);
    }
}

Deploy

Using OpenZeppelin CLI 2.8 RC

$ npx oz deploy
βœ“ Compiled contracts with solc 0.5.17 (commit.d19bba13)
? Choose the kind of deployment upgradeable
? Pick a network development
? Pick a contract to deploy Simple721Token
βœ“ Contract Simple721Token deployed
All implementations have been deployed
? Call a function to initialize the instance after creating it? Yes
? Select which function * initialize(sender: address)
? sender: address: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
βœ“ Setting everything up to create contract instances
βœ“ Instance created at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601
To upgrade this instance run 'oz upgrade'
0xCfEB869F69431e42cdB54A4F4f105C19C080A601

Mint

$ npx oz send-tx
? Pick a network development
? Pick an instance Simple721Token at 0xCfEB869F69431e42cdB54A4F4f105C19C080A601
? Select which function mint(to: address, tokenId: uint256)
? to: address: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
? tokenId: uint256: 1
βœ“ Transaction successful. Transaction hash: 0xf5e3ff127489731762c70c27a71a3b5b7ee2a1d4358679b1258eaee00c76f371
Events emitted:
 - Transfer(0x0000000000000000000000000000000000000000, 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1, 1)
1 Like