Quickstart
Quickstart (Greeter)
This quickstart will teach you how to use xcall
, the cross-chain communication primitive, to send funds and data across chains.
Introduction
In this guide, we will build a cross-chain Greeter. The DestinationGreeter
contract on the destination chain has an updateGreeting
function that changes a stored greeting
variable. The SourceGreeter
contract on the origin chain uses xcall
to send encoded calldata for updateGreeting
.
To demonstrate a combination of an asset transfer and an arbitrary call in a single xcall
, the updateGreeting
function will require a payment to update the greeting. For this example, the contract will be okay with any amount greater than 0.
updateGreeting
is implemented as an unauthenticated call (there are no checks to determine who is calling the function). Therefore, this type of xcall
will be go through the "Fast Path".
If you prefer to fork a repo instead of following this step-by-step guide, our xapp-starter kit contains a full example of this quickstart (plus more) and is compatible with both Hardhat and Foundry.
Prerequisites
Node v18 installed
Follow the instructions to install Node.js and use Node.js v18. We also recommend installing
nvm
, a node version manager, which will make switching versions easier.An Ethereum development environment like Foundry, Hardhat, Truffle, etc.
This guide will be using Hardhat. Follow the instructions to install Hardhat.
If you don't already have gas funds on Goerli, try these faucets to get some:
https://goerli-faucet.mudit.blog/ (Requires Twitter account)
https://goerlifaucet.com/ (Requires signing up with Alchemy)
Create a new project
Create a new project by running the following command:
Choose a Javascript project. Choose y
on all of the prompts.
Install the latest version of Connext contracts package in your project:
Next, install the OpenZeppelin contract package:
You'll need to manually install the library @openzeppelin/contracts-upgradeable
Install dotenv
to protect your private key needed to deploy your contract:
In the root of your project, create a new .env
file. Here you will store your private key used to deploy your contract.
Update .env
with the following line:
Source Contract
The source contract initiates the cross-chain operation with xcall
and passes the encoded greeting into the call. All xcall
params are detailed here.
In the /contracts
directory, create a new contract called SourceGreeter.sol
:
xUpdateGreeting
is what the user will call on origin to initiate the xcall
.
One important detail to note is that xUpdateGreeting
is a payable
method. This is necessary because a relayerFee
in native gas is passed into the xcall
. More on how this fee is determined later.
Compile Contract
Make sure the solidity compiler version in your hardhat.config.js
is at least 0.8.17
.
Compile the contract with the following command:
Note: Hardhat may require you to manually install dependencies for @nomicfoundation/hardhat-toolbox. If you get an error about missing dependencies for that plugin, run the following command:
Deploy Contract
Update the hardhat.config.js
file:
Create a /scripts/deploySource.js
file with the following:
The addresses for Connext and supported tokens in different domains can be referenced here. We'll be using Goerli as our origin domain and the TEST token for this contract.
Now run the deploy script:
Output:
Contract deployed to: 0x9Af84578B89FcA019580af02326388987A074ca1
Verify Contract
Add an etherScan
section to hardhat.config.js
with your goerli
api key (note: Etherscan API keys for the mainnet explorers will work for testnets):
Using the contract address you just deployed, run the hardhat verify
command, including the contract address and its constructor arguments:
If you run into any errors like ProviderError: Too Many Requests
, then replace the public RPC url in hardhat.config.js
with another one from https://chainlist.org/ or use your own private RPC from a provider like Infura or Alchemy.
Target Contract
In the /contracts
directory, create another contract called DestinationGreeter.sol
:
All target contracts must implement Connext's IXReceiver
interface. This interface ensures that Connext can call the contract and pass necessary data.
Compile Contract
Compile:
Deploy Contract
Add another entry to hardhat.config.js
, this time for Optimism-Goerli.
Create a scripts/deployTarget.js
file with the following:
Then run the deploy script:
Output:
Contract deployed to: 0xC4e508cEe84499958a84C3562e92bD9e71d7D38a
Verify Contract
Add an apiKey
to hardhat.config.js
for optimism-goerli
:
Using the contract address you just deployed, verify it:
If you run into any errors like ProviderError: Too Many Requests
, then replace the public RPC url in hardhat.config.js
with another one from https://chainlist.org/ or use your own private RPC with a provider like Infura or Alchemy.
Executing the Transaction
You should try the following steps on your own deployed contracts. For the lazy ones, you can just use these contracts we've deployed already:
Mint TEST Tokens
First, you will need some TEST tokens. Recall that the destination contract requires a payment > 0 TEST in order to update its greeting.
Since you'll be updating the greeting from the origin chain, you will need to acquire some TEST tokens on the origin chain.
You can use Etherscan to call functions on (verified) contracts. Go to the TEST Token on Etherscan and click on the "Write Contract" button.
A new tab will show up with all write functions of the contract. Connect your wallet, switch to the Goerli network, and enter the parameters for the mint
function:
account
: <YOUR_WALLET_ADDRESS>amount
: 1000000000000000000010 TEST. You can actually mint however much you want.
Approve TEST Tokens
Tokens will move from User's wallet
=> SourceGreeter
=> Connext
=> DestinationGreeter
.
The user must first approve a spending allowance of the TEST ERC20 to the SourceGreeter
contract. The require
clause starting on line 39 checks for this allowance.
Again, on the Etherscan page for the TEST token, enter the parameters for the approve
function:
spender
: 0x9Af84578B89FcA019580af02326388987A074ca1This is the address of
SourceGreeter
.
amount
: 10000000000000000000
Then "Write" to the approve
function.
Execute xUpdateGreeting
xUpdateGreeting
Similarly to the approval function for TEST, navigate to the SourceGreeter
contract on Etherscan. Fill out the xUpdateGreeting
function parameters and "Write" to the contract.
Let's walk through the different parameters.
xUpdateGreeting
(payableAmount): 0.03This is the native gas that you're sending into the
xcall
. This value must match what you pass in asrelayerFee
, but note that it's in ETH units here and wei units inrelayerFee
.
target
: 0xC4e508cEe84499958a84C3562e92bD9e71d7D38aThe address of
DestinationGreeter
.
destinationDomain
: 1735356532The Domain ID of the destination chain. You can find a mapping of Domain IDs here. For this example,
DestinationGreeter
is deployed to Optimism-Goerli.
newGreeting
: hello chain!Whatever string you want to update the greeting to.
amount
: 1000000000000000000The amount of TEST tokens to pay. We send 1 TEST here.
relayerFee
: 300000000000000000.03 goerli ETH, in wei units. Just a conservative estimate for relayers on testnet.
IMPORTANT! This is a fee paid to relayers, which are off-chain agents that help execute the final leg of the cross-chain transfer on destination. Relayers get paid in the origin chain's native asset. This is why
SourceGreeter
passes the fee like so:
As a xApp developer, you have some tools available to estimate what this relayerFee
should be. For now, there are offchain methods for doing so - check out the guide on Estimating Fees.
Track the xcall
After executing updateGreeting
, you can use Connextscan (testnet) to check the status of the xcall
. Just search up the transaction hash from the execution transaction.
Note that if your relayerFee
was too low, the explorer will prompt you to increase it.
Check DestinationGreeter
DestinationGreeter
DestinationGreeter
should be updated in just a few minutes (because this call is unauthenticated!). Cross-chain calls are not always this fast - see our guide on Authentication.
Head over to the DestinationGreeter
contract on Etherscan. This time, we'll go to the Read Contract
tab and look at the value of greeting
. It has updated!
Send a couple more updates from SourceGreeter
but make it a different string. At some point, your TEST allowance to HelloSource
will run out and you'll need to do the approval dance again.
Congrats! You've gone cross-chain!
Next Steps
Try tracking the status of an
xcall
after you send it.Learn about authentication and important security considerations.
See how nested xcalls can open up infinite cross-chain possibilities.
Fork the xApp Starter Kit (includes code for this example) and build your own xApp.
Last updated