zkBridge
  • Polyhedra Network
  • zkBridge: Trustless Cross-chain Bridges Made Practical
    • Introducing zkBridge protocol
    • Block header relay network
    • Updater contract
    • Proof systems of zkBridge
    • zkBridge Research Paper
  • zkLightClient Overview
    • Introduction
    • zkLightClient on LayerZero ​
  • LayerZero zkLightClient Configurations
    • LayerZero V1 zkLightClient Oracle Addresses
    • LayerZero V2 zkLightClient DVN Addresses
    • LayerZero UA Configuration
  • Proving Ethereum Full PoS Consensus in ZK
    • Overview
    • Why Proving Ethereum full consensus?
    • System design for proving Ethereum full consensus
    • Efficient proof system for proving Ethereum full consensus
    • Performance evaluation
    • Concluding remarks
  • Application Use Cases
    • NFT transfer
    • Message passing
  • Tutorial
    • Import and transfer NFTs
  • Code Examples
    • Deploying Cross-chain NFTs
      • Cross-chain ERC-721
      • Cross-chain ERC-1155
Powered by GitBook
On this page
  • Deploying the ERC721 NFT Contract on the Sender Chain
  • Deploying the Mapping Contract on the Receiver Chain
  1. Code Examples
  2. Deploying Cross-chain NFTs

Cross-chain ERC-721

PreviousDeploying Cross-chain NFTsNextCross-chain ERC-1155

Last updated 1 year ago

Deploying the ERC721 NFT Contract on the Sender Chain

Below is an example of a standard ERC721 contract. You can use the to deploy this contract on an EVM-compatible blockchain.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract SampleERC721 is ERC721 ,Ownable{
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;
    string private _baseTokenURI;

    constructor(string memory name, string memory symbol) ERC721(name, symbol) {}

    function mint() public {
        _safeMint(msg.sender, _tokenIds.current());
        _tokenIds.increment();
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    function setBaseURI(string calldata baseURI) external onlyOwner{
        _baseTokenURI = baseURI;
    }
}

Deploying the Mapping Contract on the Receiver Chain

For ERC721, you need to implement the IZKBridgeErc721 interface and grant minting and burning permissions to the NFT bridge contract on the receiver chain.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

interface IZKBridgeErc721 {

    function mint(address _to, uint256 _tokenId, string memory tokenURI_) external;

    function burn(uint256 _tokenId) external;

    function chainId() external view returns (uint16);

    function nativeContract() external view returns (bytes32);
}

contract ONFT is Ownable, IZKBridgeErc721, ERC721 {

    address public bridge;

    string private _baseTokenURI;

    uint16 _chainId;

    bytes32 _nativeContract;

    modifier onlyBridge() {
        require(msg.sender == bridge, "caller is not the bridge");
        _;
    }

    constructor(
        string memory _name,
        string memory _symbol,
        uint16 chainId_,
        bytes32 nativeContract_,
        address _bridge
    ) ERC721(_name, _symbol) {
        _chainId = chainId_;
        _nativeContract = nativeContract_;
        bridge = _bridge;
    }

    function mint(
        address _to,
        uint256 _tokenId,
        string memory tokenURI_
    ) external override onlyBridge {
        _mint(_to, _tokenId);
    }

    function burn(uint256 _tokenId) external override onlyBridge {
        require(_exists(_tokenId), "Burn of nonexistent token");
        _burn(_tokenId);
    }

    function chainId() external view returns (uint16) {
        return _chainId;
    }

    function nativeContract() external view returns (bytes32) {
        return _nativeContract;
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    function setBaseURI(string calldata baseURI) external onlyOwner{
        _baseTokenURI = baseURI;
    }
}

After deploying the contract on the receiver chain, please notify us and provide both the sender chain's and receiver chain's contract addresses, so we can add the mapping relationship for you.

To get in touch, you may either:

  1. Send an email to [email protected]

Example:

Once the contract is deployed, you can mint an NFT and conduct a cross-chain transfer via the . If this is the first time you are transferring this NFT, zkBridge will automatically create a mapping contract on the receiver chain. If you wish to deploy the mapping contract for the NFT on the receiver chain by yourself, please refer to the tutorial below.

Reach out to our community moderators on our

Fill out the

BscTestnet-NFT:

OpbnbTestnet-NFT:

Send Transaction Hash:

Receive Transaction Hash:

Remix - Ethereum IDE
zkBridge official website
Discord Server
from for Ecosystem Partnership
0xF6e466E4580F80Cb96bFD5D352d574a734E1f349
0xC8D3ffa9eFC55C43f598Af801A925Fd5F18bd7f4
View on BscScan
View on OpbnbScan