Challenge 4: Cross-Chain NFT Minting with Polymer


This challenge involves cross-chain communication for NFT minting and distribution. You are tasked with receiving a packet from a smart contract deployed on the Optimism blockchain. To achieve this, you will write a smart contract on Optimism that sends a query packet via Polymer to the target smart contract on Base. Upon receiving the packet, your contract should decode and send an acknowledgement back to the source contract on Optimism. This task highlights the practical use case of decentralized applications extending their functionalities across the blockchain ecosystem.

Task Details

Write a Smart Contract on Base: Create a smart contract on the Base network equipped to receive a cross-chain packet from a contract on Optimism. This contract should receive, decode the packet and send back an acknowledgement, which will mint an NFT on the source Optimism Contract
The contract on Base should use SIM Clients (non-proof) and Universal Channels to receive and send acknowledgment of packets.
Interact with the contract at address: 0x691B9bB9f262f997263FBF47F968d2B08bb5a6B8 deployed on Optimism: The source smart contract on Optimism includes an sendUniversalPacket and onUniversalPacketAcknowledgement function. These functions send universal packets to Base and then on acknowledgment, mints an NFT on Optimism. Your contract on Base should implement onRecvUniversalPacket to properly receive, format, and handle the packet to write an acknowledgment in the correct format back to Optimism. The source functions on Optimism are below:

  function sendUniversalPacket(address destPortAddr, bytes32 channelId, uint64 timeoutSeconds) external {
       string memory query = "crossChainQueryMint";
       bytes memory payload = abi.encode(msg.sender, query);
       uint64 timeoutTimestamp = uint64((block.timestamp + timeoutSeconds) * 1000000000);

           channelId, IbcUtils.toBytes32(destPortAddr), payload, timeoutTimestamp

# Other Functions

   function onUniversalAcknowledgement(bytes32 channelId, UniversalPacket memory packet, AckPacket calldata ack)
       ackPackets.push(UcAckWithChannel(channelId, packet, ack));

       // decode the counter from the ack packet
       (address caller, string memory _functionCall) = abi.decode(, (address, string));
       require(balanceOf(caller) == 0, "Caller already has an NFT");

       if (currentTokenId < 500) {
           require(keccak256(bytes(_functionCall)) == keccak256(bytes("mint")), "Invalid function call");
           emit MintAckReceived(caller, currentTokenId, "NFT minted successfully");
       } else {
           emit MintAckReceived(caller, 0, "NFT minting limit reached");
  • Receive and send Acknowledgement Packets: Your contract on Base must use Polymer’s onRecvUniversalPacket method to correctly address the contract on Base.
  • Ensure your packet’s data is correctly formatted to trigger the desired response from the Optimism contract’s onUniversalPacketAcknowledgment.
  • Verify Your Contract: To enable the broader community to review and interact with your contract—and to see the logged messages in the explorer—verify your contract on the respective blockchain explorer. This step is crucial for full transparency and authenticity.
  • Call sendUniversalPacket from the source Optimism Contract which will call your deployed contract on Base. If implemented correctly, an NFT will be minted on the source contract on Optimism

Submission Guidelines

  • Deploy your smart contract to the Base Sepolia testnet and verify its source code on the Base explorer.
  • Ensure your contract on Base correctly interfaces with the specified contract on - Optimism to receive and send the acknowledgment correctly formatted to mint the NFT.
  • Submit the address of your deployed contract on base, wallet address you used, along with a link to your NFT on the Optimism explorer.
  • Screen shot of the IBC Explorers full packet life-cycle

Judging Criteria

Submissions will be evaluated based on the following:

  • Correct implementation of the cross-chain packet sending and acknowledgment handling.
  • Successful minting of the NFT.
  • Verification of the contract source code on the blockchain explorer in order to view the code