# Mint on Source Chain

## <mark style="color:blue;">MINT</mark>&#x20;

Go to [Remix](https://remix.ethereum.org) and select the <mark style="color:blue;">CrossChainPriceNFT</mark> on the deployed contracts section in the lower lefthand side of the screen.

<figure><img src="/files/0PsTI0Y5u9K7kQEd94bi" alt=""><figcaption><p>This is what the deployed contract looks like in your Remix IDE</p></figcaption></figure>

You will want to make sure you use the <mark style="color:red;">Mint Function</mark>, and you want to provide your Wallet address as the <mark style="color:red;">parameter</mark> as you want to mint the NFTs to your <mark style="color:red;">Ethereum Sepolia walle</mark>t address.

<figure><img src="/files/cadYANChsvGzRmZRdgjz" alt=""><figcaption><p>Include your Wallet address as the Parameter</p></figcaption></figure>

* Confirm the transaction in your Metamask Wallet.

***

Once you Confirm your <mark style="color:orange;">transaction</mark>, open [testnet.opensea.io](https://testnet.opensea.io) or use the link to your collection that we saved in the last section to see your freshly minted <mark style="color:green;">NFT</mark> in the <mark style="color:purple;">Collection</mark>

<figure><img src="/files/QdDd0OPEbTD9TNeyA9KJ" alt=""><figcaption><p>Your New NFT Should have populated</p></figcaption></figure>

***

## CrossDestinationMinter.sol

On Remix open  FILE EXPLORER

<figure><img src="/files/2J7u7eVj99rIQFRUip2e" alt=""><figcaption><p>Example of the File Explorer</p></figcaption></figure>

Create a new file and name it <mark style="color:blue;">`CrossDestinationMinter.sol`</mark>

Paste this code there.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

// Deploy this contract on Sepolia

import {CCIPReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/applications/CCIPReceiver.sol";
import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";

interface InftMinter {
    function mintFrom(address account, uint256 sourceId) external;
}

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */
contract CrossDestinationMinter is CCIPReceiver {
    InftMinter public nft;

    event MintCallSuccessfull();
    // https://docs.chain.link/ccip/supported-networks/testnet
    address routerSepolia = 0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59;

    constructor(address nftAddress) CCIPReceiver(routerSepolia) {
        nft = InftMinter(nftAddress);
    }

    function _ccipReceive(
        Client.Any2EVMMessage memory message
    ) internal override {
        (bool success, ) = address(nft).call(message.data);
        require(success);
        emit MintCallSuccessfull();
    }

    function testMint() external {
        // Mint from Sepolia
        nft.mintFrom(msg.sender, 0);
    }

    function testMessage() external {
        // Mint from Sepolia
        bytes memory message;
        message = abi.encodeWithSignature("mintFrom(address,uint256)", msg.sender, 0);

        (bool success, ) = address(nft).call(message);
        require(success);
        emit MintCallSuccessfull();
    }

    function updateNFT(address nftAddress) external {
        nft = InftMinter(nftAddress);
    }
}
```

Deploy this code to <mark style="color:yellow;">Ethereum Sepolia</mark>.  The parameter is the address of your deployed C<mark style="color:blue;">rossChainPriceNFT.sol</mark> Contract , on <mark style="color:red;">Ethereum Sepolia.</mark>

<figure><img src="/files/pFF9xDEgMqAgMaqqlyvQ" alt=""><figcaption><p>Example of the Deployment tab with my CrossChainPriceNFT.sol Contract address in the NFTADDRESS parameter field</p></figcaption></figure>

We will then test it by executing <mark style="color:green;">`testMint`</mark> and <mark style="color:green;">`testMessage`</mark> on newly deployed contract <mark style="color:blue;">`CrossDestinationMinter.sol`</mark>:

<figure><img src="/files/rmws8H5tHcv96mcPzCtr" alt=""><figcaption><p>CrossDestinationMinter Deployed</p></figcaption></figure>

Click one of these functions, confirm the transaction, and when that's done click the other and confirm its transaction in Metamask.&#x20;

You can check to <mark style="color:green;">confirm</mark> that they worked by refreshing your <mark style="color:blue;">Opensea Collection</mark>

<figure><img src="/files/W2ZFRhaR4R5soTpEm67M" alt=""><figcaption><p>Example of Opensea collection after testMint &#x26; testMessage</p></figcaption></figure>

***

## CrossSourceMinter.sol

We Need to switch our network to <mark style="color:red;">Avalanche Fuji.</mark> You can do the following by going into your Metamask  and selecting "Networks", then selecting the Avalanche Fuji Network. If you dont already have the Avalanche Fuji Network Imported in your Metamask extension you can find it by going to:&#x20;

* going into your <mark style="color:red;">metamask extension</mark> and selecting networks,&#x20;
* then selecting the Avalanche Fuji Network.&#x20;
  * If you dont already have the Avalanche Fuji Network Imported in your Metamask extension you can find it by visiting [<mark style="color:blue;">chainlist</mark>](https://chainlist.org/?search=avalanche+fuji\&testnets=true)<mark style="color:blue;">.org</mark>

{% embed url="<https://chainlist.org/?search=avalanche+fuji&testnets=true>" %}
Avalanche Fuji Chainlist Quicklink
{% endembed %}

<figure><img src="/files/su8osWnL7Ah1qmWfC3j6" alt=""><figcaption><p>In the Top left of your Metamask select the Network</p></figcaption></figure>

<figure><img src="/files/5YoJvinQhfrt0ZwhEs5D" alt=""><figcaption><p>Select Avalanche Fuji</p></figcaption></figure>

Once you have switched networks, return to Remix.  In FILE EXPLORER create a new file.&#x20;

Enter the Second Icon Titled - FILE EXPLORER and create a new file.&#x20;

We will be naming this file <mark style="color:blue;">`CrossSourceMinter.sol`</mark>

<figure><img src="/files/SCdnwP59gKg2RmrwNDp5" alt=""><figcaption><p>Example of File Explorer</p></figcaption></figure>

And paste the following code in there:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

// Deploy this contract on Fuji

import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol";

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */
contract CrossSourceMinter {

    // Custom errors to provide more descriptive revert messages.
    error NotEnoughBalance(uint256 currentBalance, uint256 calculatedFees); // Used to make sure contract has enough balance to cover the fees.
    error NothingToWithdraw(); // Used when trying to withdraw but there's nothing to withdraw.

    IRouterClient public router;
    LinkTokenInterface public linkToken;
    uint64 public destinationChainSelector;
    address public owner;
    address public destinationMinter;

    event MessageSent(bytes32 messageId);

    constructor(address destMinterAddress) {
        owner = msg.sender;

        // https://docs.chain.link/ccip/supported-networks/testnet

        // from Fuji
        address routerAddressFuji = 0xF694E193200268f9a4868e4Aa017A0118C9a8177;
        router = IRouterClient(routerAddressFuji);
        linkToken = LinkTokenInterface(0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846);
        linkToken.approve(routerAddressFuji, type(uint256).max);

        // to Sepolia
        destinationChainSelector = 16015286601757825753;
        destinationMinter = destMinterAddress;
    }

    function mintOnSepolia() external {
        // Mint from Fuji network = chain[1]
        Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
            receiver: abi.encode(destinationMinter),
            data: abi.encodeWithSignature("mintFrom(address,uint256)", msg.sender, 1),
            tokenAmounts: new Client.EVMTokenAmount[](0),
            extraArgs: Client._argsToBytes(
                Client.EVMExtraArgsV1({gasLimit: 980_000})
            ),
            feeToken: address(linkToken)
        });        

        // Get the fee required to send the message
        uint256 fees = router.getFee(destinationChainSelector, message);

        if (fees > linkToken.balanceOf(address(this)))
            revert NotEnoughBalance(linkToken.balanceOf(address(this)), fees);

        bytes32 messageId;
        // Send the message through the router and store the returned message ID
        messageId = router.ccipSend(destinationChainSelector, message);
        emit MessageSent(messageId);
    }

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    function linkBalance (address account) public view returns (uint256) {
        return linkToken.balanceOf(account);
    }

    function withdrawLINK(
        address beneficiary
    ) public onlyOwner {
        uint256 amount = linkToken.balanceOf(address(this));
        if (amount == 0) revert NothingToWithdraw();
        linkToken.transfer(beneficiary, amount);
    }
}
```

Copy this code and paste it directly into your newly created <mark style="color:blue;">CrossSourceMinter.sol</mark> file in Remix

Next, we deploy this smart contract. Its <mark style="color:red;">constructor function</mark> takes the following parameter: address  of our deployed <mark style="color:blue;">`CrossDestinationMinter.sol`</mark> (deployed on Sepolia).

(this is the contract that we deployed on <mark style="color:red;">Sepolia</mark>)

<figure><img src="/files/fAc1nrJQ6wOuUqZSFqd2" alt=""><figcaption><p>Example of Deployment tab with DESTMINTERADDRESS populated with my CrossDestinationMinter.sol address</p></figcaption></figure>

If you've gotten this far congratulations! We're almost there!&#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cll-devrel.gitbook.io/bootcamp-2024/7.-chainlink-ccip-and-cross-chain-nft-dapps/mint-on-source-chain.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
