# Create Smart Contract In Remix

{% embed url="<https://remix.ethereum.org/>" fullWidth="false" %}

### Connecting MetaMask to Remix

Open up [Remix](https://remix.ethereum.org/) in the browser and go to the "DEPLOY & RUN TRANSACTIONS" icon on left side:

<div align="left"><figure><img src="https://62720068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNQrWPKDHvXg0HQjwzHbY%2Fuploads%2Fvo6MVk1wlVGPEjueiwUc%2Ffunctions42.png?alt=media&#x26;token=372d5c7e-dba0-40fe-bb14-76af3f5dc6bc" alt=""><figcaption><p>DEPLOY &#x26; RUN TRANSACTIONS ICON</p></figcaption></figure></div>

In the “ENVIRONMENT” drop-down menu, select “Injected Provider - MetaMask”:

<div align="left"><figure><img src="https://62720068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNQrWPKDHvXg0HQjwzHbY%2Fuploads%2FuMTrLwlQM9xXO4FYL6xF%2Ffunctions43.png?alt=media&#x26;token=952c183c-1210-4823-bc04-632b4e8225fb" alt=""><figcaption><p>Select Injected Provider - MetaMask</p></figcaption></figure></div>

Make sure you are on Custom (43113) network, which is Avalanche Fuji Testnet:

<div align="left"><figure><img src="https://62720068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNQrWPKDHvXg0HQjwzHbY%2Fuploads%2FnNdXJftZvze0EhP99K6J%2Ffunctions44.png?alt=media&#x26;token=d7c0fdb9-c129-48b6-9f1b-f82c84a18933" alt=""><figcaption><p>Connected to (43113) - Avalanche Fuji Testnet</p></figcaption></figure></div>

{% hint style="info" %}
If you are not connect to different network, go into MetaMask and connect to the Avalanche Fuji Testnet
{% endhint %}

***

### Creating your Smart Contract

Create a smart contract called `TransferUSDCBasic.sol`. First, go to the 1. “FILE EXPLORER” icon and then click the 2. “Create new file” icon:

<div align="left"><figure><img src="https://62720068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNQrWPKDHvXg0HQjwzHbY%2Fuploads%2FzglhzZ6DPYf0mYoKIGPt%2Fremix6.png?alt=media&#x26;token=b7307b70-9e7c-4e20-bd15-f9600f552ef2" alt=""><figcaption><p>Create a new Solidity file</p></figcaption></figure></div>

Name the new Solidity file `TransferUSDCBasic.sol` and a new tab will open in Remix:

<figure><img src="https://62720068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNQrWPKDHvXg0HQjwzHbY%2Fuploads%2FJnryE7dkVTvEKFiMJVMH%2Fremix5.png?alt=media&#x26;token=389584fd-a5dd-4bd7-b123-852ce9f36cfe" alt=""><figcaption><p>Your new blank Solidity file</p></figcaption></figure>

* Code is available here: [GitHub](https://github.com/solangegueiros/chainlink-bootcamp-2024/blob/main/TransferUSDCBasic.sol)
* Copy and paste the code into the new `TransferUSDCBasic.sol` file
* Or copy and paste this following code:

{% code title="TransferUSDCBasic.sol" %}

```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 {IERC20} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/token/ERC20/IERC20.sol";
import {SafeERC20} from "@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/token/ERC20/utils/SafeERC20.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 TransferUSDCBasic {
    using SafeERC20 for IERC20;

    error NotEnoughBalanceForFees(uint256 currentBalance, uint256 calculatedFees);
    error NotEnoughBalanceUsdcForTransfer(uint256 currentBalance);
    error NothingToWithdraw();

    address public owner;
    IRouterClient private immutable ccipRouter;
    IERC20 private immutable linkToken;
    IERC20 private immutable usdcToken;

    // https://docs.chain.link/ccip/supported-networks/v1_2_0/testnet#avalanche-fuji
    address ccipRouterAddress = 0xF694E193200268f9a4868e4Aa017A0118C9a8177;

    // https://docs.chain.link/resources/link-token-contracts#fuji-testnet
    address linkAddress = 0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846;

    // https://developers.circle.com/stablecoins/docs/usdc-on-test-networks
    address usdcAddress = 0x5425890298aed601595a70AB815c96711a31Bc65;

    // https://docs.chain.link/ccip/supported-networks/v1_2_0/testnet#ethereum-sepolia
    uint64 destinationChainSelector = 16015286601757825753;

    event UsdcTransferred(
        bytes32 messageId,
        uint64 destinationChainSelector,
        address receiver,
        uint256 amount,
        uint256 ccipFee
    );

    constructor() {
        owner = msg.sender;
        ccipRouter = IRouterClient(ccipRouterAddress);
        linkToken = IERC20(linkAddress);
        usdcToken = IERC20(usdcAddress);
    }

    function transferUsdcToSepolia(
        address _receiver,
        uint256 _amount
    )
        external
        returns (bytes32 messageId)
    {
        Client.EVMTokenAmount[]
            memory tokenAmounts = new Client.EVMTokenAmount[](1);
        Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({
            token: address(usdcToken),
            amount: _amount
        });
        tokenAmounts[0] = tokenAmount;

        Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
            receiver: abi.encode(_receiver),
            data: "",
            tokenAmounts: tokenAmounts,
            extraArgs: Client._argsToBytes(
                Client.EVMExtraArgsV1({gasLimit: 0})
            ),
            feeToken: address(linkToken)
        });

        uint256 ccipFee = ccipRouter.getFee(
            destinationChainSelector,
            message
        );

        if (ccipFee > linkToken.balanceOf(address(this)))
            revert NotEnoughBalanceForFees(linkToken.balanceOf(address(this)), ccipFee);
        linkToken.approve(address(ccipRouter), ccipFee);

        if (_amount > usdcToken.balanceOf(msg.sender))
            revert NotEnoughBalanceUsdcForTransfer(usdcToken.balanceOf(msg.sender));
        usdcToken.safeTransferFrom(msg.sender, address(this), _amount);
        usdcToken.approve(address(ccipRouter), _amount);

        // Send CCIP Message
        messageId = ccipRouter.ccipSend(destinationChainSelector, message);

        emit UsdcTransferred(
            messageId,
            destinationChainSelector,
            _receiver,
            _amount,
            ccipFee
        );
    }

    function allowanceUsdc() public view returns (uint256 usdcAmount) {
        usdcAmount = usdcToken.allowance(msg.sender, address(this));
    }

    function balancesOf(address account) public view returns (uint256 linkBalance, uint256 usdcBalance) {
        linkBalance =  linkToken.balanceOf(account);
        usdcBalance = IERC20(usdcToken).balanceOf(account);
    }

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

    function withdrawToken(
        address _beneficiary,
        address _token
    ) public onlyOwner {
        uint256 amount = IERC20(_token).balanceOf(address(this));
        if (amount == 0) revert NothingToWithdraw();
        IERC20(_token).transfer(_beneficiary, amount);
    }
}
```

{% endcode %}
