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.
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
xUpdateGreetingSimilarly 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,
DestinationGreeteris 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
SourceGreeterpasses the fee like so:
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
DestinationGreeterDestinationGreeter 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
xcallafter 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