Skip to content

Commit

Permalink
add upgradable
Browse files Browse the repository at this point in the history
  • Loading branch information
andresaiello committed Jul 1, 2024
1 parent d288a04 commit ec6702b
Show file tree
Hide file tree
Showing 7 changed files with 903 additions and 243 deletions.
10 changes: 10 additions & 0 deletions packages/zevm-app-contracts/contracts/xp-nft/test/xpNFTV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

import "../xpNFT.sol";

contract ZetaXPV2 is ZetaXP {
function version() public pure override returns (string memory) {
return "2.0.0";
}
}
72 changes: 19 additions & 53 deletions packages/zevm-app-contracts/contracts/xp-nft/xpNFT.sol
Original file line number Diff line number Diff line change
@@ -1,44 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract ZetaXP is ERC721URIStorage, Ownable {
contract ZetaXP is ERC721Upgradeable, OwnableUpgradeable {
/* An ECDSA signature. */
struct Signature {
uint8 v;
bytes32 r;
bytes32 s;
}

struct Task {
bool completed;
uint256 count;
}

struct ZetaXPData {
uint256 xpTotal;
uint256 level;
uint256 testnetCampaignParticipant;
uint256 enrollDate;
uint256 mintDate;
uint256 generation;
}

struct UpdateData {
address to;
uint256 tokenId;
ZetaXPData xpData;
uint256[] taskIds;
Task[] taskValues;
Signature signature;
uint256 sigTimestamp;
uint256 signedUp;
}

mapping(uint256 => ZetaXPData) public zetaXPData;
mapping(uint256 => mapping(uint256 => Task)) public tasksByTokenId;
mapping(uint256 => uint256) lastUpdateTimestampByTokenId;
mapping(uint256 => uint256) signedUpByTokenId;

// Base URL for NFT images
string public baseTokenURI;
Expand All @@ -54,23 +37,30 @@ contract ZetaXP is ERC721URIStorage, Ownable {
error TransferNotAllowed();
error OutdatedSignature();

constructor(
function initialize(
string memory name,
string memory symbol,
string memory baseTokenURI_,
address signerAddress_
) ERC721(name, symbol) {
) public initializer {
__ERC721_init(name, symbol);
__Ownable_init();
baseTokenURI = baseTokenURI_;
signerAddress = signerAddress_;
}

function version() public pure virtual returns (string memory) {
return "1.0.0";
}

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

function tokenURI(uint256 tokenId) public view override(ERC721URIStorage) returns (string memory) {
return super.tokenURI(tokenId);
return string(abi.encodePacked(baseTokenURI, _uint2str(tokenId)));
}

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

Expand Down Expand Up @@ -113,49 +103,25 @@ contract ZetaXP is ERC721URIStorage, Ownable {

// Function to compute the hash of the data and tasks for a token
function _calculateHash(UpdateData memory updateData) private pure returns (bytes32) {
ZetaXPData memory xpData = updateData.xpData;
bytes memory encodedData = abi.encode(
updateData.to,
updateData.tokenId,
updateData.sigTimestamp,
xpData.xpTotal,
xpData.level,
xpData.testnetCampaignParticipant,
xpData.enrollDate,
xpData.mintDate,
xpData.generation
updateData.signedUp
);

for (uint256 i = 0; i < updateData.taskIds.length; i++) {
encodedData = abi.encode(
encodedData,
updateData.taskIds[i],
updateData.taskValues[i].completed,
updateData.taskValues[i].count
);
}

return keccak256(encodedData);
}

function _updateNFT(UpdateData memory updateData) internal {
_verify(updateData);
lastUpdateTimestampByTokenId[updateData.tokenId] = updateData.sigTimestamp;
ZetaXPData memory xpData = updateData.xpData;
zetaXPData[updateData.tokenId] = xpData;

if (updateData.taskIds.length != updateData.taskValues.length) revert LengthMismatch();

zetaXPData[updateData.tokenId] = updateData.xpData;
for (uint256 i = 0; i < updateData.taskIds.length; i++) {
tasksByTokenId[updateData.tokenId][updateData.taskIds[i]] = updateData.taskValues[i];
}
signedUpByTokenId[updateData.tokenId] = updateData.signedUp;
}

// External mint function
function mintNFT(UpdateData calldata mintData) external {
_mint(mintData.to, mintData.tokenId);
_setTokenURI(mintData.tokenId, string(abi.encodePacked(baseTokenURI, _uint2str(mintData.tokenId))));

_updateNFT(mintData);

Expand Down
1 change: 1 addition & 0 deletions packages/zevm-app-contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import "@nomicfoundation/hardhat-verify";
import "@nomiclabs/hardhat-waffle";
import "@typechain/hardhat";
import "@openzeppelin/hardhat-upgrades";
import "hardhat-gas-reporter";
import "solidity-coverage";
import "tsconfig-paths/register";
Expand Down
2 changes: 2 additions & 0 deletions packages/zevm-app-contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
},
"dependencies": {
"@openzeppelin/contracts": "4.9.3",
"@openzeppelin/contracts-upgradeable": "4.9.3",
"@openzeppelin/hardhat-upgrades": "^1.7.0-rc.0",
"@uniswap/v2-periphery": "1.1.0-beta.0",
"@zetachain/networks": "^4.0.0",
"@zetachain/protocol-contracts": "^4.0.1",
Expand Down
40 changes: 3 additions & 37 deletions packages/zevm-app-contracts/test/xp-nft/test.helpers.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { ethers } from "hardhat";

export interface Task {
completed: boolean;
count: number;
}

export interface ZetaXPData {
enrollDate: number;
generation: number;
level: number;
mintDate: number;
testnetCampaignParticipant: number;
xpTotal: number;
}

export interface Signature {
r: string;
s: string;
v: number;
}

export interface NFT {
taskIds: number[];
taskValues: Task[];
signedUp: number;
to: string;
tokenId: number;
xpData: ZetaXPData;
}

export interface UpdateParam extends NFT {
Expand All @@ -41,29 +25,11 @@ export const getSignature = async (
tokenId: number,
nft: NFT
) => {
const { xpData } = nft;
let payload = ethers.utils.defaultAbiCoder.encode(
["address", "uint256", "uint256", "uint256", "uint256", "uint256", "uint256", "uint256", "uint256"],
[
to,
tokenId,
timestamp,
xpData.xpTotal,
xpData.level,
xpData.testnetCampaignParticipant,
xpData.enrollDate,
xpData.mintDate,
xpData.generation,
]
["address", "uint256", "uint256", "uint256"],
[to, tokenId, timestamp, nft.signedUp]
);

for (let i = 0; i < nft.taskIds.length; i++) {
payload = ethers.utils.defaultAbiCoder.encode(
["bytes", "uint256", "bool", "uint256"],
[payload, nft.taskIds[i], nft.taskValues[i].completed, nft.taskValues[i].count]
);
}

const payloadHash = ethers.utils.keccak256(payload);

// This adds the message prefix
Expand Down
Loading

0 comments on commit ec6702b

Please sign in to comment.