Skip to content

Commit

Permalink
feat: Update nft contract to calculate tokenid (#167)
Browse files Browse the repository at this point in the history
* feat: Update nft contract to calculate tokenid

* deploy and verify
  • Loading branch information
andresaiello authored Aug 15, 2024
1 parent b0132b4 commit 9ef6dba
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 86 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@types/node": "^17.0.25",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"@zetachain/toolkit": "^5.0.0",
"@zetachain/toolkit": "10.0.0",
"chai": "^4.3.6",
"dotenv": "^16.0.0",
"eslint": "^8.13.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,7 @@ contract WithdrawERC20 {

(address gasZRC20, uint256 gasFee) = IZRC20(zrc20).withdrawGasFee();

uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens(
systemContract.wZetaContractAddress(),
systemContract.uniswapv2FactoryAddress(),
systemContract.uniswapv2Router02Address(),
zrc20,
gasFee,
gasZRC20,
amount
);
uint256 inputForGas = SwapHelperLib.swapTokensForExactTokens(systemContract, zrc20, gasFee, gasZRC20, amount);

if (inputForGas > amount) revert InsufficientInputAmount();

Expand Down
54 changes: 31 additions & 23 deletions packages/zevm-app-contracts/contracts/xp-nft/xpNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,27 @@ contract ZetaXP is ERC721Upgradeable, OwnableUpgradeable {

struct UpdateData {
address to;
uint256 tokenId;
Signature signature;
uint256 sigTimestamp;
uint256 signedUp;
bytes32 tag;
}

mapping(uint256 => uint256) lastUpdateTimestampByTokenId;
mapping(uint256 => uint256) signedUpByTokenId;
mapping(uint256 => uint256) public lastUpdateTimestampByTokenId;
mapping(uint256 => uint256) public signedUpByTokenId;
mapping(uint256 => bytes32) public tagByTokenId;

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

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

// Event for New Mint
event NFTMinted(address indexed sender, uint256 indexed tokenId);
event NFTMinted(address indexed sender, uint256 indexed tokenId, bytes32 tag);
// Event for NFT Update
event NFTUpdated(address indexed sender, uint256 indexed tokenId);
event NFTUpdated(address indexed sender, uint256 indexed tokenId, bytes32 tag);

error InvalidSigner();
error LengthMismatch();
Expand All @@ -47,6 +51,7 @@ contract ZetaXP is ERC721Upgradeable, OwnableUpgradeable {
__Ownable_init();
baseTokenURI = baseTokenURI_;
signerAddress = signerAddress_;
_currentTokenId = 1; // Start token IDs from 1
}

function version() public pure virtual returns (string memory) {
Expand Down Expand Up @@ -86,7 +91,7 @@ contract ZetaXP is ERC721Upgradeable, OwnableUpgradeable {
return string(bstr);
}

function _verify(UpdateData memory updateData) private view {
function _verify(uint256 tokenId, UpdateData memory updateData) private view {
bytes32 payloadHash = _calculateHash(updateData);
bytes32 messageHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", payloadHash));

Expand All @@ -98,43 +103,46 @@ contract ZetaXP is ERC721Upgradeable, OwnableUpgradeable {
);

if (signerAddress != messageSigner) revert InvalidSigner();
if (updateData.sigTimestamp <= lastUpdateTimestampByTokenId[updateData.tokenId]) revert OutdatedSignature();
if (updateData.sigTimestamp <= lastUpdateTimestampByTokenId[tokenId]) revert OutdatedSignature();
}

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

return keccak256(encodedData);
}

function _updateNFT(UpdateData memory updateData) internal {
_verify(updateData);
lastUpdateTimestampByTokenId[updateData.tokenId] = updateData.sigTimestamp;
signedUpByTokenId[updateData.tokenId] = updateData.signedUp;
function _updateNFT(uint256 tokenId, UpdateData memory updateData) internal {
_verify(tokenId, updateData);
lastUpdateTimestampByTokenId[tokenId] = updateData.sigTimestamp;
signedUpByTokenId[tokenId] = updateData.signedUp;
}

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

_updateNFT(newTokenId, mintData);

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

emit NFTMinted(mintData.to, mintData.tokenId);
_currentTokenId++; // Increment the token ID for the next mint
}

// External mint function
function updateNFT(UpdateData memory updateData) external {
address owner = ownerOf(updateData.tokenId);
// External update function
function updateNFT(uint256 tokenId, UpdateData memory updateData) external {
address owner = ownerOf(tokenId);
updateData.to = owner;
_updateNFT(updateData);
_updateNFT(tokenId, updateData);

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

// Set the base URI for tokens
Expand Down
11 changes: 10 additions & 1 deletion packages/zevm-app-contracts/data/addresses.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@
"zetaSwapBtcInbound": "0x358E2cfC0E16444Ba7D3164Bbeeb6bEA7472c559",
"invitationManager": "0x3649C03C472B698213926543456E9c21081e529d",
"withdrawERC20": "0xa349B9367cc54b47CAb8D09A95836AE8b4D1d84E",
"ZetaXP": "0x80ECE9a08ba893e1B863C0c6B3c098268C146E40"
"ZetaXP": "0xE1DfA5dfd1d6c6b47C8c9b8726EdD019D365491D"
},
"zeta_mainnet": {
"disperse": "0x23ce409Ea60c3d75827d04D9db3d52F3af62e44d",
"rewardDistributorFactory": "0xB9dc665610CF5109cE23aBBdaAc315B41FA094c1",
"zetaSwap": "0xA8168Dc495Ed61E70f5c1941e2860050AB902cEF",
"zetaSwapBtcInbound": "0x358E2cfC0E16444Ba7D3164Bbeeb6bEA7472c559",
"invitationManager": "0x3649C03C472B698213926543456E9c21081e529d",
"withdrawERC20": "0xa349B9367cc54b47CAb8D09A95836AE8b4D1d84E",
"ZetaXP": "0x6926b6ea978d59a8Ab6aC05486Fd0bED6D15eC29"
}
}
}
24 changes: 23 additions & 1 deletion packages/zevm-app-contracts/scripts/xp-nft/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isProtocolNetworkName } from "@zetachain/protocol-contracts";
import { ethers, network, upgrades } from "hardhat";
import { ethers, network, run, upgrades } from "hardhat";

import { ZetaXP__factory } from "../../typechain-types";
import { saveAddress } from "../address.helpers";
Expand All @@ -9,6 +9,20 @@ const networkName = network.name;
const ZETA_BASE_URL = "https://api.zetachain.io/nft/";
const signer = "0x1d24d94520B94B26351f6573de5ef9731c48531A";

const verifyContract = async (contractAddress: string, constructorArguments: any[]) => {
// Verification process
console.log(`Verifying contract ${contractAddress}...`);
try {
await run("verify:verify", {
address: contractAddress,
constructorArguments,
});
console.log("Verification successful");
} catch (error) {
console.error("Verification failed:", error);
}
};

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

Expand All @@ -17,8 +31,16 @@ const deployZetaXP = async () => {

await zetaXP.deployed();

// Get the implementation address
const implementationAddress = await upgrades.erc1967.getImplementationAddress(zetaXP.address);

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

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

await verifyContract(zetaXP.address, ["ZETA NFT", "ZNFT", ZETA_BASE_URL, signer]);
await verifyContract(implementationAddress, []);
};

const main = async () => {
Expand Down
15 changes: 5 additions & 10 deletions packages/zevm-app-contracts/test/xp-nft/test.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,20 @@ export interface Signature {

export interface NFT {
signedUp: number;
tag: string;
to: string;
tokenId: number;
}

export interface UpdateParam extends NFT {
sigTimestamp: number;
signature: Signature;
tokenId: number;
}

export const getSignature = async (
signer: SignerWithAddress,
timestamp: number,
to: string,
tokenId: number,
nft: NFT
) => {
export const getSignature = async (signer: SignerWithAddress, timestamp: number, to: string, nft: NFT) => {
let payload = ethers.utils.defaultAbiCoder.encode(
["address", "uint256", "uint256", "uint256"],
[to, tokenId, timestamp, nft.signedUp]
["address", "uint256", "uint256", "bytes32"],
[to, timestamp, nft.signedUp, nft.tag]
);

const payloadHash = ethers.utils.keccak256(payload);
Expand Down
Loading

0 comments on commit 9ef6dba

Please sign in to comment.