I am missing something conceptually about override the _authorizeUpgrade
function when composing two contracts. The setting is that I have two contracts, both upgradeable, as follows:
contract ERC721UpgradeableV1 is Initializable, ERC721Upgradeable, ERC721URIStorageUpgradeable, UUPSUpgradeable {
...
constructor() {
_disableInitializers();
}
function initializeERC721UpgradeableV1(string memory _name, string memory _symbol, string memory uri, address witness ) initializer public {
__ERC721_init(_name,_symbol);
__ERC721URIStorage_init();
__UUPSUpgradeable_init();
baseURI = uri;
admin721 = msg.sender;
witness721 = witness;
isPaused = true;
isWhitelistOnly = true;
}
function _authorizeUpgrade(address newImplementation) internal override {
require(msg.sender == admin721 || msg.sender == witness721);
}
....
}
contract PaymentSplitterUpgradeable is Context, ReentrancyGuard, Initializable, UUPSUpgradeable {
...
/**
* @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
* the matching position in the `shares` array.
*
* All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
* duplicates in `payees`.
*/
function initializePaymentSplitter( address witness_, address[] memory payees, uint256[] memory shares_) payable public initializer {
require(payees.length == shares_.length, "PaymentSplitterUpgradeable: payees and shares length mismatch");
require(payees.length > 0, "PaymentSplitterUpgradeable: no payees");
paymentWitness = witness_;
paymentOwner = msg.sender;
_addPayoutWindow( payees, shares_);
}
function _authorizeUpgrade(address newImplementation) internal override {
require(msg.sender == paymentOwner || msg.sender == paymentWitness);
}
}
Now I am trying to write an upgradeable version of the two contracts via:
contract ERC721PaymentSplitterV1 is
Initializable,
UUPSUpgradeable,
ERC721UpgradeableV1,
PaymentSplitterUpgradeable
{
/**
* @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE`, and `PAUSER_ROLE` to the account that
* deploys the contract.
*/
function initializeERC721LumoPaymentSplitter(
string memory _name,
string memory _symbol,
string memory uri,
address witness_,
address[] memory _payees,
uint256[] memory _shares
) initializer public {
initializeERC721UpgradeableV1(_name, _symbol, uri, witness_);
initializePaymentSplitter(witness_, _payees, _shares);
}
function _authorizeUpgrade(address newImplementation)
internal
override
{}
}
And receive a rather severe message about the function _authorizeUpgrade
in ERC721PaymentSplitterV1
with:
`TypeError: Trying to override non-virtual function. Did you forget to add "virtual"?
--> contracts/project/ERC721UpgradeableV1.sol:38:5:
|
38 | function _authorizeUpgrade(address newImplementation) internal override {
| ^ (Relevant source part starts here and spans across multiple lines).
Note: Overriding function is here:
--> contracts/project/ERC721PaymentSplitter.sol:32:5:
|
32 | function _authorizeUpgrade(address newImplementation)
| ^ (Relevant source part starts here and spans across multiple lines).
TypeError: Trying to override non-`
ote: This contract:
--> @openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:22:1:
|
22 | abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
| ^ (Relevant source part starts here and spans across multiple lines).
Note: This contract:
--> contracts/project/ERC721Lumo.sol:10:1:
TypeError: Derived contract must override function "_msgData". Two or more base classes define function with same name and parameter types.
--> contracts/project/ERC721PaymentSplitter.sol:9:1: