Hey! I'm trying to understand how the deployment of a UUPSUpgradeable contract works.
I created a simple one using the openzeppelin wizard:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract MyToken is Initializable, ERC721Upgradeable, ERC721URIStorageUpgradeable, OwnableUpgradeable, UUPSUpgradeable {
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize() initializer public {
__ERC721_init("MyToken", "MTK");
__ERC721URIStorage_init();
__Ownable_init();
__UUPSUpgradeable_init();
}
function safeMint(address to, uint256 tokenId, string memory uri)
public
onlyOwner
{
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
function _authorizeUpgrade(address newImplementation)
internal
onlyOwner
override
{}
// The following functions are overrides required by Solidity.
function _burn(uint256 tokenId)
internal
override(ERC721Upgradeable, ERC721URIStorageUpgradeable)
{
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721Upgradeable, ERC721URIStorageUpgradeable)
returns (string memory)
{
return super.tokenURI(tokenId);
}
}
I know that with Remix, it is possible to use the "Deploy with proxy" function that magically does everything. I also know that there are tools to automate. But I want to understand why manually I can't. How to build and initialize the proxy?
I noticed that Remix uses openzeppelin code (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/ERC1967/ERC1967Proxy.sol) as a Proxy.
So I did the same thing. First I deployed my contract (MyToken). Then I deployed the ERC1967Proxy using the constructor parameters:
_LOGIC: the address of the MyToken contract
_DATE: 0x
And then it doesn't work
What was left to do?