How to send ERC-20 tokens transactions using Ethers JS and JavaScript

In this tutorial, we are going to learn how to send ERC-20 tokens to another wallet using Ethers JS and JavaScript. You will learn how to interact with an ERC-20 smart contract.

In this tutorial, we are going to learn how to send ERC-20 tokens to another wallet using Ethers JS and JavaScript. You will learn how to interact with an ERC-20 smart contract.

ERC-20 is the standard for tokens on Ethereum and EVM blockchains. Thanks to that standard, we can use the same code to send any token, because they all have the transfer function and all the same functions and data in general.

Here is the code to do that (example sending 100 USDT to another address):

const ethers = require("ethers")

const provider = new ethers.providers.Web3Provider(YOUR_PROVIDER_HERE)

const signer = provider.getSigner()

// The token address
const contractAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7"

// The smart contract ABI
const ABI = [
    {
        "constant":false,
        "inputs":[
            {"name":"_to","type":"address"},
            {"name":"_value","type":"uint256"}
        ],
        "name":"transfer",
        "outputs":[],
        "payable":false,
        "stateMutability":"nonpayable",
        "type":"function"
    }
]

// Create a Contract instance
// Since it creates a transaction, we need to pass a Signer
const contract = new ethers.Contract(contractAddress, ABI, signer);


// Call the transfer function of the smart contract

const to = "0x5b8f1310A956ee1521A7bB56160451C786289aa9"

// USDT has only 6 decimals of precision so we need to convert the token amount that way:
const amount = ethers.utils.parseUnits("100", 6) // send 100 tokens

// Other tokens have 18 decimals of precision so you need to do this to transfer 100 tokens:
// const amount = ethers.utils.parseEther("100")


// Send the transfer transaction
const transferTx = await contract.transfer(to, amount)

Now let's break down this code.

Creating a Contract instance

First, you need to create an instance of the Contract object so we can call the functions of the smart contract.

To create that instance, we need the contract address and an ABI.

An ABI is an interface that defines what functions the smart contract has and how they are defined (what arguments they can take in and what they return).

You can find both the address and the ABI token you want by searching for the name of the token on Etherscan.

At the top of the token's page you'll find the contract address that you can copy:

Then, if you go to the "Contract" tab and on the "Code" section:

And scroll down a bit, you'll find the full ABI of the smart contract for all its functions:

You don't have to use the full ABI in your code, the ABI just needs to have the functions that you're going to use.

In our case, we just need the transfer function which looks like this:

const ABI = [
    {
        "constant":false,
        "inputs":[
            {"name":"_to","type":"address"},
            {"name":"_value","type":"uint256"}
        ],
        "name":"transfer",
        "outputs":[],
        "payable":false,
        "stateMutability":"nonpayable",
        "type":"function"
    }
]

// OR

// in Solidity-like code:
const ABI = [
    "function transfer(address _to, uint256 _value)"
]

Once you have the ABI and the token address, you can create the Contract instance using a Signer:

const contract = new ethers.Contract(address, ABI, signer)

Note that a Wallet instance is also a valid Signer.

Calling the transfer function to send ERC-20 tokens

Now that you have your Contract instance, you can to call the transfer function. It takes in parameter the address that you want to send the tokens to and the amount of tokens you want to send.

The recipient address is just a string but the amount of tokens needs to be in a specific unit.

Tokens have 18 decimals of precision, you can see it in the Etherscan page of the token.
That means to send a specific amount of tokens, you need to pass that amount with 18 decimals of precision which corresponds to an Ethereum sub-unit called wei.

It's exactly like when you want to send Ethereum, the value to send needs to be in wei.

USDT and other USD stable coins have only 6 decimals of precision so we need to convert the amount of tokens to send into a different unit.

For USDT or USDC, the amount would be (of course, replace 100 by the amount you want to send):

const amount = ethers.utils.parseUnits("100", 6)

And for other tokens with 18 decimals of precision:

const amount = ethers.utils.parseEther("100")

Now, to send the tokens, we call the transfer function:

// Example for USDT

const to = "0x5b8f1310A956ee1521A7bB56160451C786289aa9"
const amount = ethers.utils.parseUnits("100", 6) // send 100 USDT

const transferTx = await contract.transfer(to, amount)

And for non-stablecoin tokens like UNI:

// Example for another token

const contractAddress = "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"

const ABI = [
    {
        "constant":false,
        "inputs":[
            {"name":"_to","type":"address"},
            {"name":"_value","type":"uint256"}
        ],
        "name":"transfer",
        "outputs":[],
        "payable":false,
        "stateMutability":"nonpayable",
        "type":"function"
    }
]

const to = "0x5b8f1310A956ee1521A7bB56160451C786289aa9"
const amount = ethers.utils.parseEther("100") // send 100 UNI

const contract = new ethers.Contract(contractAddress, ABI, signer)

const transferTx = await contract.transfer(to, amount)

The transfer function sends a transaction so it returns a TransactionResponse object. To learn more about it, check out the official documentation here.

Or you can have an explanation of the TransactionResponse object in our guide about how to get a transaction state (it's in the first part where we talk about the getTransaction function):

How to get the state of a transaction using Ethers JS and JavaScript
In this tutorial, we are going to learn how to get the state of a transaction using Ethers JS and JavaScript.

Bonus

Check out this guide if you want to learn how to interact with any smart contract and not just ERC-20 smart contracts:

How to interact with a smart contract using Ethers JS and JavaScript
In this tutorial, we are going to learn how to interact with a smart contract using Ethers JS and JavaScript. We are going to see how to read data from a smart contract and send transactions to it.

And that's it 🎉

Thank you for reading this article