Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
andresaiello committed Oct 17, 2024
1 parent d911826 commit fb40350
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 155 deletions.
6 changes: 3 additions & 3 deletions packages/zevm-app-contracts/contracts/xp-nft/xpNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "@openzeppelin/contracts/utils/Strings.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";

contract ZetaXP is ERC721Upgradeable, Ownable2StepUpgradeable, EIP712Upgradeable {
bytes32 private constant MINTORUPDATE_TYPEHASH =
bytes32 internal constant MINTORUPDATE_TYPEHASH =
keccak256("MintOrUpdateNFT(address to,uint256 signatureExpiration,uint256 sigTimestamp,bytes32 tag)");

struct UpdateData {
Expand All @@ -28,7 +28,7 @@ contract ZetaXP is ERC721Upgradeable, Ownable2StepUpgradeable, EIP712Upgradeable
address public signerAddress;

// Counter for the next token ID
uint256 private _currentTokenId;
uint256 internal _currentTokenId;

// Event for New Mint
event NFTMinted(address indexed sender, uint256 indexed tokenId, bytes32 tag);
Expand Down Expand Up @@ -97,7 +97,7 @@ contract ZetaXP is ERC721Upgradeable, Ownable2StepUpgradeable, EIP712Upgradeable
return super.supportsInterface(interfaceId);
}

function _verify(uint256 tokenId, UpdateData memory updateData) private view {
function _verify(uint256 tokenId, UpdateData memory updateData) internal view {
bytes32 structHash = keccak256(
abi.encode(
MINTORUPDATE_TYPEHASH,
Expand Down
159 changes: 7 additions & 152 deletions packages/zevm-app-contracts/contracts/xp-nft/xpNFT_V2.sol
Original file line number Diff line number Diff line change
@@ -1,38 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "./xpNFT.sol";

contract ZetaXP_V2 is ERC721Upgradeable, Ownable2StepUpgradeable, EIP712Upgradeable {
bytes32 private constant MINTORUPDATE_TYPEHASH =
keccak256("MintOrUpdateNFT(address to,uint256 signatureExpiration,uint256 sigTimestamp,bytes32 tag)");

bytes32 private constant SETLEVEL_TYPEHASH =
contract ZetaXP_V2 is ZetaXP {
bytes32 internal constant SETLEVEL_TYPEHASH =
keccak256("SetLevel(uint256 tokenId,uint256 signatureExpiration,uint256 sigTimestamp,uint256 level)");

struct UpdateData {
address to;
bytes signature;
uint256 signatureExpiration;
uint256 sigTimestamp;
bytes32 tag;
}

mapping(uint256 => uint256) public lastUpdateTimestampByTokenId;
mapping(uint256 => bytes32) public tagByTokenId;
mapping(address => mapping(bytes32 => uint256)) public tokenByUserTag;

// Base URL for NFT images
string public baseTokenURI;
address public signerAddress;

// Counter for the next token ID
uint256 private _currentTokenId;

struct SetLevelData {
uint256 tokenId;
bytes signature;
Expand All @@ -43,137 +17,18 @@ contract ZetaXP_V2 is ERC721Upgradeable, Ownable2StepUpgradeable, EIP712Upgradea

mapping(uint256 => uint256) public levelByTokenId;

// Event for New Mint
event NFTMinted(address indexed sender, uint256 indexed tokenId, bytes32 tag);
// Event for NFT Update
event NFTUpdated(address indexed sender, uint256 indexed tokenId, bytes32 tag);
// Event for Signer Update
event SignerUpdated(address indexed signerAddress);
// Event for Base URI Update
event BaseURIUpdated(string baseURI);
// Event for Level Set
event LevelSet(address indexed sender, uint256 indexed tokenId, uint256 level);

error InvalidSigner();
error SignatureExpired();
error InvalidAddress();
error LengthMismatch();
error TransferNotAllowed();
error OutdatedSignature();
error TagAlreadyHoldByUser();

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function initialize(
string memory name,
string memory symbol,
string memory baseTokenURI_,
address signerAddress_,
address owner
) public initializer {
if (signerAddress_ == address(0)) revert InvalidAddress();
__EIP712_init("ZetaXP", "1");
__ERC721_init(name, symbol);
__Ownable_init();
transferOwnership(owner);
baseTokenURI = baseTokenURI_;
signerAddress = signerAddress_;
_currentTokenId = 1; // Start token IDs from 1
}

function version() public pure returns (string memory) {
function version() public pure override returns (string memory) {
return "2.0.0";
}

// Internal function to set the signer address
function setSignerAddress(address signerAddress_) external onlyOwner {
if (signerAddress_ == address(0)) revert InvalidAddress();
signerAddress = signerAddress_;
emit SignerUpdated(signerAddress_);
}

// Set the base URI for tokens
function setBaseURI(string calldata _uri) external onlyOwner {
baseTokenURI = _uri;
emit BaseURIUpdated(_uri);
}

// The following functions are overrides required by Solidity.
function tokenURI(uint256 tokenId) public view override(ERC721Upgradeable) returns (string memory) {
_requireMinted(tokenId);

return string(abi.encodePacked(baseTokenURI, Strings.toString(tokenId)));
}

function supportsInterface(bytes4 interfaceId) public view override(ERC721Upgradeable) returns (bool) {
return super.supportsInterface(interfaceId);
}

function _verifyUpdateNFTSignature(uint256 tokenId, UpdateData memory updateData) private view {
bytes32 structHash = keccak256(
abi.encode(
MINTORUPDATE_TYPEHASH,
updateData.to,
updateData.signatureExpiration,
updateData.sigTimestamp,
updateData.tag
)
);
bytes32 constructedHash = _hashTypedDataV4(structHash);

if (!SignatureChecker.isValidSignatureNow(signerAddress, constructedHash, updateData.signature)) {
revert InvalidSigner();
}

if (block.timestamp > updateData.signatureExpiration) revert SignatureExpired();
if (updateData.sigTimestamp <= lastUpdateTimestampByTokenId[tokenId]) revert OutdatedSignature();
}

function _updateNFT(uint256 tokenId, UpdateData memory updateData) internal {
_verifyUpdateNFTSignature(tokenId, updateData);
lastUpdateTimestampByTokenId[tokenId] = updateData.sigTimestamp;
tagByTokenId[tokenId] = updateData.tag;
tokenByUserTag[updateData.to][updateData.tag] = tokenId;
}

// External mint function with auto-incremented token ID
function mintNFT(UpdateData memory mintData) external {
uint256 newTokenId = _currentTokenId;
_mint(mintData.to, newTokenId);

if (tokenByUserTag[mintData.to][mintData.tag] != 0) revert TagAlreadyHoldByUser();
_updateNFT(newTokenId, mintData);

emit NFTMinted(mintData.to, newTokenId, mintData.tag);

_currentTokenId++; // Increment the token ID for the next mint
}

// External update function
function updateNFT(uint256 tokenId, UpdateData memory updateData) external {
address owner = ownerOf(tokenId);
updateData.to = owner;
bool willUpdateTag = tagByTokenId[tokenId] != updateData.tag;

if (willUpdateTag) {
if (tokenByUserTag[owner][updateData.tag] != 0) revert TagAlreadyHoldByUser();
tokenByUserTag[owner][tagByTokenId[tokenId]] = 0;
}

_updateNFT(tokenId, updateData);

emit NFTUpdated(owner, tokenId, updateData.tag);
}

function _transfer(address from, address to, uint256 tokenId) internal override {
revert TransferNotAllowed();
function _verifyUpdateNFTSignature(uint256 tokenId, UpdateData memory updateData) internal view {
_verify(tokenId, updateData);
}

Check warning

Code scanning / Slither

Dead-code Warning


// V2 Methods
function _verifySetLevelSignature(SetLevelData memory data) private view {
function _verifySetLevelSignature(SetLevelData memory data) internal view {
bytes32 structHash = keccak256(
abi.encode(SETLEVEL_TYPEHASH, data.tokenId, data.signatureExpiration, data.sigTimestamp, data.level)
);
Expand Down

0 comments on commit fb40350

Please sign in to comment.