Skip to main content

EVM To EVM Token Transfer Example


In the following example, we will use the TESTNET environment to perform a cross-chain ERC-20 transfer with an ERC20LRTST token. The transfer will be initiated on the EVM-side via the Goerli Ethereum testnet and received on the EVM-side via the Sepolia Ethereum testnet.

EVM-to-EVM Token Transfer Example

This is an example script that demonstrates the functionality of the Sygma SDK and the wider Sygma ecosystem of bridges, fee handlers, and relayers. The script showcases an ERC-20 token transfer between two networks using the Sygma SDK. The complete example can be found in this repo.


Before running the script, ensure that you have the following:

  • Node.js installed on your machine
  • Yarn (version 3.4.1 or higher)
  • Access to an Ethereum provider
  • A wallet funded with ERC20LRTest or gPHA tokens from the Sygma faucet
  • Goerli ETH for gas

We make use of the dotenv module to manage exported private keys with environment variables. Please note that accidentally committing a .env file containing private keys to a wallet with real funds, onto GitHub, could result in the complete loss of your funds. Never expose your private keys.

Getting Started

  1. Clone the repository

Clone the sygma-sdk repository into a directory of your choice, and then cd into the folder:

git clone [email protected]:sygmaprotocol/sygma-sdk.git
cd sygma-sdk/
  1. Install dependencies

Install the project dependencies by running:

yarn install
  1. Build the SDK

Build the SDK by running the following command:

yarn sdk:build
  1. Usage

To send an ERC-20 example transfer from EVM to Substrate, cd into the example folder examples/evm-to-evm-fungible-transfer and run:

cd examples/evm-to-evm-fungible-transfer
yarn run transfer

The example will use ethers in conjunction with the sygma-sdk to create a transfer from Goerli to Sepolia with the ERC20LRTST token. It will be received on Sepolia as the ERC20LRTST token.

Script Functionality

This example script performs the following steps:

  • Initializes the SDK by importing the required packages and defining the constants for the script.
import { EVMAssetTransfer, Environment } from "@buildwithsygma/sygma-sdk-core";
import { Wallet, providers } from "ethers";

const SEPOLIA_CHAIN_ID = 11155111;
  • Configures the dotenv module and sets the privateKey as a value to be pulled from the .env file.
import dotenv from "dotenv";


const privateKey = process.env.PRIVATE_KEY;

if (!privateKey) {
throw new Error("Missing environment variable: PRIVATE_KEY");
  • Defines the ERC-20 transfer function.
export async function erc20Transfer(): Promise<void> {
  • Set up the provider, wallet, and asset transfer objects using the TESTNET environment.
  const provider = new providers.JsonRpcProvider(
const wallet = new Wallet(
privateKey as string,
const assetTransfer = new EVMAssetTransfer();
await assetTransfer.init(provider, Environment.TESTNET);
  • Constructs a transfer object that defines the details of the ERC-20 token transfer using the previously declared constants, as well as the amount to be transferred. As we specify the getAddress method from the ethers.js wallet module for our recipient, the recipient will be the same address but on a different test network.
  const transfer = assetTransfer.createFungibleTransfer(
await wallet.getAddress(),
await wallet.getAddress(), // Sending to the same address on a different chain
"50000000000000000000" // 18 decimal places, so in this case, 50 tokens would be sent
  • Retrieves the fee required to complete the transfer from the SDK.
  • Builds the necessary approval transactions for the transfer and sends them using the Ethereum wallet. The approval transactions are required to authorize the transfer of ERC-20 tokens.
  const fee = await assetTransfer.getFee(transfer);
const approvals = await assetTransfer.buildApprovals(transfer, fee);
for (const approval of approvals) {
const response = await wallet.sendTransaction(
approval as providers.TransactionRequest
console.log("Sent approval with hash: ", response.hash);
  • Builds the final transfer transaction and sends it using the Ethereum wallet.
  const transferTx = await assetTransfer.buildTransferTransaction(
const response = await wallet.sendTransaction(
transferTx as providers.TransactionRequest
console.log("Sent transfer with hash: ", response.hash);