Hey folks,
I am converting my contract to Upgradeable using UUPS. I generated the contract skeleton via OpenZeppelin Wizard and I am curious about a few things:
- ProxyAdmin is the deployer address. I thought it would only be allowed to call upgrade-related functions, but from my unit tests, proxyAdmin can call contract functions such as safeMint();
In my research, it is advised to have a ProxyAdmin who can upgrade contracts, but cannot call contract funcions, and create a contract owner (do not confuse with token owner) who is allowed to call contract functions (like safeMint) but cannot upgrade contract.
Can you please point me to documentation regarding this separation of roles and how to implement it?
- I have implemented ERC721BurnableUpgradeable and I would like only the contract owner to be able to burn tokens. Right now, the token owner is allowed to burn,
Contract burn code (no changes from OpenZeppelin Wizard):
function _burn(uint256 tokenId)
internal
override(
ERC721Upgradeable,
ERC721URIStorageUpgradeable,
ERC721RoyaltyUpgradeable
)
{
super._burn(tokenId);
}
Test:
it("Token owner cannot burn", async function () {
// deploy contract
const { contract, annAccount } = await loadFixture(deployFixture);
// mint token to annAccount
await contract.safeMint(annAccount.address, tokenOne, ipfsFirstToken);
// check Ann received the token
await expect(
contract.balanceOf(annAccount.address)
).to.eventually.equal(1);
// Ann cannot burn her token
await expect(
contract.connect(annAccount).burn(tokenOne)
).to.revertedWith("Ownable: caller is not the owner");
// Ann still has her token
await expect(
contract.balanceOf(annAccount.address)
).to.eventually.equal(1);
});
Test result:
Deploying
Proxy Admin: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Contract deployed to: 0x70e0bA845a1A0F2DA3359C97E0285013525FFC49
AssertionError: Expected transaction to be reverted with reason 'Ownable: caller is not the owner', but it didn't revert
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Context.<anonymous> (test\Contract.js:260:9)
Oddly, proxyAdmin (deployer contract) cannot burn. If I switch the burn statement on test for this:
await contract.burn(tokenOne);
Then I get this error:
'ERC721: caller is not token owner nor approved'
How can I only allow contract owner (or proxyAdmin in my current scenario) to be the only one allowed to burn a token?
Thanks in advance!