Skip to content

Commit

Permalink
feat: change the nft metadata (#192)
Browse files Browse the repository at this point in the history
* feat: Change the NFT metadata

* add upgrade script

* fix deploy script
  • Loading branch information
andresaiello authored Oct 17, 2024
1 parent cda1529 commit 89275a0
Show file tree
Hide file tree
Showing 7 changed files with 937 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import "../xpNFT.sol";

contract ZetaXPV2 is ZetaXP {
function version() public pure override returns (string memory) {
return "2.0.0";
return "1.0.1";
}
}
50 changes: 50 additions & 0 deletions packages/zevm-app-contracts/contracts/xp-nft/xpNFT_V2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "./xpNFT.sol";

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

struct SetLevelData {
uint256 tokenId;
bytes signature;
uint256 signatureExpiration;
uint256 sigTimestamp;
uint256 level;
}

mapping(uint256 => uint256) public levelByTokenId;
event LevelSet(address indexed sender, uint256 indexed tokenId, uint256 level);

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

function _verifySetLevelSignature(SetLevelData memory data) private view {
bytes32 structHash = keccak256(
abi.encode(SETLEVEL_TYPEHASH, data.tokenId, data.signatureExpiration, data.sigTimestamp, data.level)
);
bytes32 constructedHash = _hashTypedDataV4(structHash);

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

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

function setLevel(SetLevelData memory data) external {
_verifySetLevelSignature(data);

levelByTokenId[data.tokenId] = data.level;
lastUpdateTimestampByTokenId[data.tokenId] = data.sigTimestamp;
emit LevelSet(msg.sender, data.tokenId, data.level);
}

function getLevel(uint256 tokenId) external view returns (uint256) {
return levelByTokenId[tokenId];
}
}
35 changes: 35 additions & 0 deletions packages/zevm-app-contracts/scripts/xp-nft/upgrade-v2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { isProtocolNetworkName } from "@zetachain/protocol-contracts";
import { ethers, network, upgrades } from "hardhat";

import addresses from "../../data/addresses.json";
import { saveAddress } from "../address.helpers";
import { verifyContract } from "../explorer.helpers";

const networkName = network.name;

const upgradeZetaXP = async () => {
if (!isProtocolNetworkName(networkName)) throw new Error("Invalid network name");

//@ts-ignore
const nftAddress = addresses["zevm"][networkName].ZetaXP;

const ZetaXPFactory = await ethers.getContractFactory("ZetaXP_V2");
const zetaXP = await upgrades.upgradeProxy(nftAddress, ZetaXPFactory);
const implementationAddress = await upgrades.erc1967.getImplementationAddress(zetaXP.address);

console.log("ZetaXP upgraded in:", zetaXP.address);
console.log("ZetaXP implementation deployed to:", implementationAddress);

saveAddress("ZetaXP", zetaXP.address, networkName);

await verifyContract(implementationAddress, []);
};

const main = async () => {
await upgradeZetaXP();
};

main().catch((error) => {
console.error(error);
process.exit(1);
});
36 changes: 36 additions & 0 deletions packages/zevm-app-contracts/test/xp-nft/test.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,39 @@ export const getSignature = async (
const signature = await signer._signTypedData(domain, types, value);
return signature;
};

export const getSelLevelSignature = async (
chainId: number,
verifyingContract: string,
signer: SignerWithAddress,
signatureExpiration: number,
timestamp: number,
tokenId: number,
level: number
) => {
const domain = {
chainId: chainId,
name: "ZetaXP",
verifyingContract: verifyingContract,
version: "1",
};

const types = {
SetLevel: [
{ name: "tokenId", type: "uint256" },
{ name: "signatureExpiration", type: "uint256" },
{ name: "sigTimestamp", type: "uint256" },
{ name: "level", type: "uint256" },
],
};

const value = {
level,
sigTimestamp: timestamp,
signatureExpiration,
tokenId,
};
// Signing the data
const signature = await signer._signTypedData(domain, types, value);
return signature;
};
Loading

0 comments on commit 89275a0

Please sign in to comment.