Skip to content

Instantly share code, notes, and snippets.

@rafat
Created January 16, 2024 17:15
Show Gist options
  • Save rafat/a498ea46e356fb5ce9cf5de5ea7eae21 to your computer and use it in GitHub Desktop.
Save rafat/a498ea46e356fb5ce9cf5de5ea7eae21 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.19+commit.7dd6d404.js&optimize=false&runs=200&gist=
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
// Deploy this contract on Mumbai
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 CrossSourceMinterMumbai {
// 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
// from Fuji
address routerAddressMumbai = 0x1035CabC275068e0F4b745A29CEDf38E13aF41b1;
router = IRouterClient(routerAddressMumbai);
linkToken = LinkTokenInterface(0x326C977E6efc84E512bB9C30f76E30c160eD06FB);
linkToken.approve(routerAddressMumbai, type(uint256).max);
// to Sepolia
destinationChainSelector = 16015286601757825753;
destinationMinter = destMinterAddress;
}
function mintOnSepolia() external {
// Mint from Mumbai network = chain[2]
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(destinationMinter),
data: abi.encodeWithSignature("mintFrom(address,uint256)", msg.sender, 2),
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);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment