The RARE Bridge is a set of smart contracts developed to facilitate the transfer and distribution of RARE tokens between different blockchain networks using Chainlink Cross-Chain Interoperability Protocol (CCIP). The bridge ensures secure and efficient communication across chains, allowing for seamless token transfers and distribution.
- Purpose: This abstract upgradable contract defines the core functionality for sending and receiving RARE tokens across different blockchain networks using Chainlink CCIP.
- Key Features:
- Handles token transfer and distribution.
- Manages allowlists for senders and recipients to enhance security.
- Supports customization of default gas limits for different destination chains.
- Emits events for sent and received messages for transparency and tracking.
- Purpose: Implements the lock-and-unlock mechanism for the
RareBridge
contract. - Key Features:
- Handles locking tokens on the source chain and unlocking them on the destination chain.
- Purpose: Implements the burn-and-mint mechanism for the
RareBridge
contract. - Key Features:
- Handles burning tokens on the source chain and minting them on the destination chain.
- Purpose: Upgradable ERC20 token contract for the RARE token on Layer 2 networks.
- Key Features:
- Standard upgradable and pausable ERC20 with minting and burning functionality and zero initial supply.
- Purpose: Extends the functionality of the
CCIPReceiver
contract to support upgradeability through the UUPS (Universal Upgradeable Proxy Standard) pattern. - Key Features:
- Provides initialization methods for setting up the CCIP router.
- Implements the
ccipReceive
function to handle incoming CCIP messages.
- Purpose: Interface defining the events and errors for the
RareBridge
contract. - Key Features:
- Defines events for message sending and receiving activities.
- Defines errors for bridge interactions.
- Purpose: Example. Extends the
RareBridge
contract to add withdrawable functionality. - Key Features:
- Implements methods for withdrawing tokens from the bridge contract.
In this project, the deployment scripts utilize .env
template files to manage environment variables.
Each deployment or configuration script is associated with a specific .env
template file.
When a script is executed, the corresponding template file is copied to .env
to provide environment variables to Solidity scripts executed, and specific .env.L1
or .env.L2
files are sourced to provide the RPC_URL, PRIVATE_KEY and ETHERSCAN_API_KEY environment variables for Forge at runtime.
Here are the scripts and their associated .env
templates:
deployRareBridge:L1
: Uses.env.deployBridgeL1
and sources.env.L1
.deployAndConfigureRareBridge:L2
: Uses.env.deployAndConfigureBridgeL2
and sources.env.L2
.configureRareBridge:L1
: Uses.env.configureBridgeL1
and sources.env.L1
.sendTokens:L1:L2
: Uses.env.sendTokensL1L2
and sources.env.L1
.sendTokens:L2:L1
: Uses.env.sendTokensL2L1
and sources.env.L2
.
The environment files should be filled with the appropriate values before executing the scripts.
- Node.js and npm installed. Follow the Node.js Installation documentation.
- Forge installed for building and deploying Solidity contracts. Follow the Foundry Installation and Foundry Getting Started documentation.
- Install Dependencies: Ensure all dependencies are installed.
npm install && forge install
- Build Contracts: Build the contracts using Forge.
npm run build
Deploy the RareBridgeLockAndUnlock
contract on the source chain (Layer 1).
This script uses environment variables specified in .env.deployBridgeL1
to configure the deployment process:
CCIP_ROUTER_ADDRESS
- address of the Chainlink CCIP router on the source chain.LINK_TOKEN_ADDRESS
- address of the Chainlink LINK token on the source chain.RARE_TOKEN_ADDRESS
- address of the RARE token on the source chain.
The script will:
-
Source
.env.L1
to load runtime environment variables. -
Copy the
.env.deployBridgeL1
template to.env
for deployment-specific configurations. -
Deploy the Rare Bridge proxy and
RareBridgeLockAndUnlock
implementation contracts. -
Broadcast the transaction to the network using Forge with the specified RPC URL and private key.
-
Verify the deployed contract on Etherscan using the provided API key.
npm run deployBridge:L1
Note
Themsg.sender
will be set as the Rare Bridge admin.
You can reassign the admin role to another address later.
Alternatively, you can use the RareBridgeDeployLockAndUnlock.s.sol script.
Deploy and configure the RareBridgeBurnAndMint
contract on the destination chain (Layer 2).
This script uses environment variables specified in .env.deployAndConfigureBridgeL2
to configure the deployment process:
CCIP_ROUTER_ADDRESS
- address of the Chainlink CCIP router on the destination chain.LINK_TOKEN_ADDRESS
- address of the Chainlink LINK token on the destination chain.CORRESPONDENT_RARE_BRIDGE_ADDRESS
- address of the Rare Bridge contract on the source chain.CORRESPONDENT_CHAIN_SELECTOR
- chain selector for the source chain.CORRESPONDENT_CHAIN_GAS_LIMIT
- gas limit for theccipReceive()
method on the source chain.
The script will:
-
Source
.env.L2
to load runtime environment variables. -
Copy the
.env.deployAndConfigureBridgeL2
template to.env
for deployment-specific configurations. -
Deploy the
RareTokenL2
proxy and implementation contracts. -
Deploy the Rare Bridge proxy and
RareBridgeBurnAndMint
implementation contracts. -
Set the deployed Rare Bridge contract as the minter for the
RareTokenL2
contract. -
Configure the Rare Bridge by allowlisting source chain and the source Rare Bridge, and setting default the gas limit for the source chain.
-
Broadcast the transactions to the network using Forge with the specified RPC URL and private key.
-
Verify the deployed contracts on Etherscan using the provided API key.
npm run deployAndConfigureBridge:L2
Note
Themsg.sender
will be set as the Rare Bridge admin.
You can reassign the admin role to another address later.
Alternatively, you can use the RareBridgeDeployBurnAndMint.s.sol script.
Configure the RareBridge
contract on the source chain (Layer 1).
This script uses environment variables specified in .env.configureBridgeL1
:
RARE_BRIDGE_ADDRESS
- address of the Rare Bridge contract on the source chain.CORRESPONDENT_RARE_BRIDGE_ADDRESS
- address of the Rare Bridge contract on the destination chain.CORRESPONDENT_CHAIN_SELECTOR
- chain selector for the destination chain.CORRESPONDENT_CHAIN_GAS_LIMIT
- gas limit for theccipReceive()
method on the destination chain.
The script will:
-
Source
.env.L1
to load runtime environment variables. -
Copy the
.env.configureBridgeL1
template to.env
for deployment-specific configurations. -
Configure the Rare Bridge contract by allowlisting destination chain and the destination Rare Bridge, and setting default the gas limit for the destination chain.
-
Broadcast the transactions to the network using Forge with the specified RPC URL and private key.
npm run configureBridge:L1
Send tokens from the source chain (Layer 1) to the destination chain (Layer 2).
This script uses environment variables specified in .env.sendTokensL1L2
:
RARE_TOKEN_ADDRESS
- address of the Rare Token on the source chain.LINK_TOKEN_ADDRESS
- address of the Chainlink LINK token on the source chain.RARE_BRIDGE_ADDRESS
- address of the Rare Bridge contract on the source chain.CORRESPONDING_RARE_BRIDGE_ADDRESS
- address of the Rare Bridge contract on the destination chain.CORRESPONDING_CHAIN_SELECTOR
- chain selector for the destination chain.AMOUNTS
- comma-separated array of token amounts to send.RECIPIENTS
- comma-separated array of recipient addresses.PAY_FEES_IN_LINK
- boolean indicating whether to pay fees in LINK tokens (true) or in the native cryptocurrency (false)
The script will:
-
Source
.env.L1
to load runtime environment variables. -
Copy the
.env.sendTokensL1L2
template to.env
for deployment-specific configurations. -
Calculate fees for sending tokens based on the specified parameters.
-
Approve the Rare Bridge contract to spend the specified amounts of RARE and LINK tokens.
-
Call the
sendTokens
method on the Rare Bridge contract to send and distribute tokens to the destination chain. -
Broadcast the transactions to the network using Forge with the specified RPC URL and private key.
npm run sendTokens:L1:L2
Send tokens from the destination chain (Layer 2) back to the source chain (Layer 1).
This script uses environment variables specified in .env.sendTokensL2L1
:
RARE_TOKEN_ADDRESS
- address of the Rare Token on the destination chain.LINK_TOKEN_ADDRESS
- address of the Chainlink LINK token on the destination chain.RARE_BRIDGE_ADDRESS
- address of the Rare Bridge contract on the destination chain.CORRESPONDING_RARE_BRIDGE_ADDRESS
- address of the Rare Bridge contract on the source chain.CORRESPONDING_CHAIN_SELECTOR
- chain selector for the source chain.AMOUNTS
- comma-separated array of token amounts to send.RECIPIENTS
- comma-separated array of recipient addresses.PAY_FEES_IN_LINK
- boolean indicating whether to pay fees in LINK tokens (true) or in the native cryptocurrency (false)
The script will:
-
Source
.env.L2
to load runtime environment variables. -
Copy the
.env.sendTokensL2L1
template to.env
for deployment-specific configurations. -
Calculate fees for sending tokens based on the specified parameters.
-
Approve the Rare Bridge contract to spend the specified amounts of RARE and LINK tokens.
-
Call the
sendTokens
method on the Rare Bridge contract to send and distribute tokens to the destination chain. -
Broadcast the transactions to the network using Forge with the specified RPC URL and private key.
npm run sendTokens:L2:L1
Estimate CCIP Receiver gas usage while sending a CCIP message to a destination chain.
This script uses environment variables specified in .env.ccipReceiveEstimateGas
:
RPC_URL
- RPC URL of the destination chain.SOURCE_RARE_BRIDGE_ADDRESS
- whitelisted address of the Rare Bridge contract on the source chain.SOURCE_CHAIN_SELECTOR
- whitelisted chain selector for the source chain.CCIP_ROUTER_ADDRESS
- address of the Chainlink CCIP router on the destination chain.CCIP_RECEIVER_ADDRESS
- address of the CCIP Receiver contract (Rare Bridge) on the destination chain.AUTO_PREPARE_SCENARIO
- boolean indicating whether to prepare the scenario automatically (true) or manually (false).NUM_RECIPIENTS
- number of recipients to estimate gas for (ifAUTO_PREPARE_SCENARIO
is true).AMOUNTS
- comma-separated array of token amounts to send.RECIPIENTS
- comma-separated array of recipient addresses.
The script will:
-
Copy the
.env.ccipReceiveEstimateGas
template to.env
for deployment-specific configurations. -
Fork the destination chain with the
RPC_URL
provided. -
Read or generate recipient addresses and token amounts based on the specified parameters.
-
Generate CCIP message with the specified parameters.
-
Call the
ccipReceive
method on the Rare Bridge contract in a forked environment. -
Show the output in the console: gas usage, number of recipients, and the message data size in bytes.
npm run ccipReceiverEstimateGas
The Rare Bridge emits events for sent and received messages. These events can be used to monitor and track messages sent from the source chain and received on the destination chain.
This event is emitted when a message is sent to a destination chain.
event MessageSent(
bytes32 indexed messageId,
uint64 indexed destinationChainSelector,
address indexed destinationChainRecipient,
uint256 fee,
bool payFeesInLink
);
messageId
- The unique ID of the CCIP message. This ID can be used to track the message through its lifecycle.destinationChainSelector
- The selector of the destination chain, indicating which chain the message is being sent to.destinationChainRecipient
- The address of the CCIP recipient on the destination chain. This is the address that will handle the message on the destination chain.fee
- The amount of fees paid for sending the message. This can help in understanding the cost of the transaction.payFeesInLink
- A boolean indicating whether the fees were paid in LINK tokens (true) or in the native cryptocurrency (false).
This event is emitted when a message is received from a sender chain.
event MessageReceived(
bytes32 indexed messageId,
uint64 indexed sourceChainSelector,
address indexed sourceChainSender
);
messageId
- The unique ID of the CCIP message. This ID can be used to track the message through its lifecycle.sourceChainSelector
- The selector of the source chain, indicating which chain the message is coming from.sourceChainSelector
- The address of the CCIP sender on the source chain. This is the address that originally sent the message on the source chain.
To track the current status of CCIP messages, you can use the Chainlink CCIP Explorer by providing the CCIP Message ID or Tx Hash: https://ccip.chain.link/.
To upgrade the Rare Bridge contracts, you can use the UUPS (Universal Upgradeable Proxy Standard) pattern.
The RareBridge
, RareBridgeLockAndUnlock
, and RareBridgeBurnAndMint
contracts are designed to be upgradeable. You can deploy new implementations of these contracts and update the proxy contracts to point to the new implementations.
In order to test the upgrade functionality, you can use the provided script RareBridgeUpgradeWithdrawable.s.sol. This script deploys a new example implementation contract RareBridgeWithdrawable.sol and updates the proxy contract to point to the new implementation.
Chainlink-related parameters, including CCIP Router addresses, LINK Token addresses, and Chain Selectors, can be found in the documentation for Chainlink CCIP:
While sending tokens from Layer 1 to Layer 2 and back, ensure that the gas limit is correctly set. This parameter should align with the number of token recipients. You can estimate the gas usage and message data size using the dedicated script: Estimate CCIP Receiver gas usage.
Alternatively, you can follow the documentation and tutorials provided by Chainlink: https://docs.chain.link/ccip/tutorials/ccipreceive-gaslimit.
Please refer to the CCIP Service Limits when setting the gas limit and sending a CCIP message.