-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: NFT and FT upgradeable using OpenZeppelin's UUPS #6
base: main
Are you sure you want to change the base?
Changes from 27 commits
560abc1
9cbb94d
6b8e43c
76b927b
76ecec6
7b75695
e56a27b
3299510
c10a0c4
2703523
2d20568
510ad53
41115ea
9ca161f
a3f58ba
fd3d640
fcab2fa
76b5c25
326c16b
b5767bb
dcae400
a2fd412
1d52473
9d9834e
f62a780
f61fb4f
3b9a093
0b208f1
565a6fe
99d2b08
ae1b1d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,3 +17,5 @@ cache_forge | |
access_token | ||
|
||
localnet.json | ||
|
||
.openzeppelin |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,49 +2,78 @@ | |
pragma solidity 0.8.26; | ||
|
||
import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; | ||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; | ||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; | ||
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; | ||
import "@openzeppelin/contracts/access/Ownable2Step.sol"; | ||
import "@zetachain/protocol-contracts/contracts/evm/GatewayEVM.sol"; | ||
import {RevertContext} from "@zetachain/protocol-contracts/contracts/Revert.sol"; | ||
import "../shared/Events.sol"; | ||
|
||
abstract contract UniversalNFT is | ||
ERC721, | ||
ERC721Enumerable, | ||
ERC721URIStorage, | ||
Ownable2Step, | ||
Events | ||
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; | ||
import {ERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; | ||
import {ERC721EnumerableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol"; | ||
import {ERC721URIStorageUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"; | ||
import {ERC721BurnableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol"; | ||
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; | ||
|
||
import "../shared/UniversalNFTEvents.sol"; | ||
|
||
contract UniversalNFT is | ||
Initializable, | ||
ERC721Upgradeable, | ||
ERC721EnumerableUpgradeable, | ||
ERC721URIStorageUpgradeable, | ||
ERC721BurnableUpgradeable, | ||
OwnableUpgradeable, | ||
UUPSUpgradeable, | ||
UniversalNFTEvents | ||
{ | ||
GatewayEVM public immutable gateway; | ||
GatewayEVM public gateway; | ||
uint256 private _nextTokenId; | ||
address public universal; | ||
uint256 public immutable gasLimitAmount; | ||
uint256 public gasLimitAmount; | ||
|
||
error InvalidAddress(); | ||
error Unauthorized(); | ||
error InvalidGasLimit(); | ||
error GasTokenTransferFailed(); | ||
|
||
function setUniversal(address contractAddress) external onlyOwner { | ||
if (contractAddress == address(0)) revert InvalidAddress(); | ||
universal = contractAddress; | ||
emit SetUniversal(contractAddress); | ||
} | ||
|
||
modifier onlyGateway() { | ||
if (msg.sender != address(gateway)) revert Unauthorized(); | ||
_; | ||
} | ||
|
||
constructor(address payable gatewayAddress, uint256 gas) { | ||
/// @custom:oz-upgrades-unsafe-allow constructor | ||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize( | ||
address initialOwner, | ||
string memory name, | ||
string memory symbol, | ||
address payable gatewayAddress, | ||
uint256 gas | ||
) public initializer { | ||
__ERC721_init(name, symbol); | ||
__ERC721Enumerable_init(); | ||
__ERC721URIStorage_init(); | ||
__Ownable_init(initialOwner); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in general ownable is ok but AccessControl.sol gives more granular roles and overall better, worth checking for furhter improvements imo There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
__ERC721Burnable_init(); | ||
__UUPSUpgradeable_init(); | ||
if (gatewayAddress == address(0)) revert InvalidAddress(); | ||
if (gas == 0) revert InvalidGasLimit(); | ||
gasLimitAmount = gas; | ||
gateway = GatewayEVM(gatewayAddress); | ||
} | ||
|
||
function setGasLimit(uint256 gas) external onlyOwner { | ||
if (gas == 0) revert InvalidGasLimit(); | ||
gasLimitAmount = gas; | ||
} | ||
|
||
function setUniversal(address contractAddress) external onlyOwner { | ||
if (contractAddress == address(0)) revert InvalidAddress(); | ||
universal = contractAddress; | ||
emit SetUniversal(contractAddress); | ||
} | ||
|
||
function safeMint(address to, string memory uri) public onlyOwner { | ||
uint256 hash = uint256( | ||
keccak256( | ||
|
@@ -134,30 +163,35 @@ abstract contract UniversalNFT is | |
emit TokenTransferReverted(sender, tokenId, uri); | ||
} | ||
|
||
receive() external payable {} | ||
|
||
fallback() external payable {} | ||
|
||
// The following functions are overrides required by Solidity. | ||
|
||
function _update( | ||
address to, | ||
uint256 tokenId, | ||
address auth | ||
) internal override(ERC721, ERC721Enumerable) returns (address) { | ||
) | ||
internal | ||
override(ERC721Upgradeable, ERC721EnumerableUpgradeable) | ||
returns (address) | ||
{ | ||
return super._update(to, tokenId, auth); | ||
} | ||
|
||
function _increaseBalance( | ||
address account, | ||
uint128 value | ||
) internal override(ERC721, ERC721Enumerable) { | ||
) internal override(ERC721Upgradeable, ERC721EnumerableUpgradeable) { | ||
super._increaseBalance(account, value); | ||
} | ||
|
||
function tokenURI( | ||
uint256 tokenId | ||
) public view override(ERC721, ERC721URIStorage) returns (string memory) { | ||
) | ||
public | ||
view | ||
override(ERC721Upgradeable, ERC721URIStorageUpgradeable) | ||
returns (string memory) | ||
{ | ||
return super.tokenURI(tokenId); | ||
} | ||
|
||
|
@@ -166,9 +200,19 @@ abstract contract UniversalNFT is | |
) | ||
public | ||
view | ||
override(ERC721, ERC721Enumerable, ERC721URIStorage) | ||
override( | ||
ERC721Upgradeable, | ||
ERC721EnumerableUpgradeable, | ||
ERC721URIStorageUpgradeable | ||
) | ||
returns (bool) | ||
{ | ||
return super.supportsInterface(interfaceId); | ||
} | ||
|
||
function _authorizeUpgrade( | ||
address newImplementation | ||
) internal override onlyOwner {} | ||
|
||
receive() external payable {} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.26; | ||
|
||
import "../evm/UniversalNFT.sol"; | ||
|
||
contract EVMUniversalNFT is UniversalNFT {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just curious why we need this empty contract? we have evm/UniversalNFT and zetachain/UniversalNFT, so they are already different paths? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ThirdWeb uses contract names as identifiers, so they should be unique (not the path, names). |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.26; | ||
|
||
import "../zetachain/UniversalNFT.sol"; | ||
|
||
contract ZetaChainUniversalNFT is UniversalNFT {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we also call init for ERC721BurnableUpgradeable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
326c16b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also added burnable to universal token contract.