Comment on page
How to Create and Deploy an XRC20 Token Using Hardhat and TypeScript
Use TypeScript and Hardhat to deploy an XRC20 Token.

hardhat
Hardhat is a development environment to compile, deploy, test, and debug your Ethereum software. Get Solidity stack traces & console.log.
In this tutorial, you will learn how to set up Hardhat and use it to build, test, and deploy a XRC20 token on both the XDC Network mainnet and XDC Apothem testnet.
- Install and setup Hardhat
- Create an XRC20 token
- Compile the XRC20 token
- Deploy the XRC20 token
- Interact with the XRC20 token
XRC20 is a set of rules to standardize assets on the XinFin network. Every XRC20 token must be able to execute the following methods:
totalSupply()
balanceOf(address account)
allowance(address owner, address spender)
transfer(address recipient, uint amount)
approve(address spender, uint amount)
transferFrom(address sender, address recipient, uint amount)
These are the minimum required methods that allow an asset on the XDC Network to be called an XRC20 token. Also, a XRC20 token must be able to emit the following
Events
on the blockchain:Approval(address indexed tokenOwner, address indexed spender, uint tokens)
Transfer(address indexed from, address indexed to, uint tokens)
Events come in handy in the exhaustive labor of indexing state changes, and they are essential for off-chain applications to find relevant data on the blockchain. By mapping all
Transfer
events, for example, we can fetch all the historic data on token transfers more easily.In addition, a few contract constants that are public that are also very important to have are:
name
symbol
decimals
Without these public constants, it would be impossible to label tokens on block explorers, for example. In this tutorial, we will deploy a XRC20 token that have all the
Methods
, Events
, and Constants
mentioned above.There are a few technical requirements before we start. Please install the following:
Next, set up your folder. As we are creating a project called
XRC20
, create a new XRC20
folder by running the following on terminal:mkdir XRC20 && cd XRC20
We can get started with Hardhat by running:
npx hardhat
The following message will show on your console. Hit
y
to continue or just press ENTER
:Need to install the following packages:
hardhat
Ok to proceed? (y)
The following message should log on your console:

hardhat config
Press
↓
and ENTER
to get started with a new TypeScript Hardhat Project. You will then be presented with the following options:✔ Hardhat project root: · /Users/cr/XRC20
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Help us improve Hardhat with anonymous crash reports & basic usage data? (Y/n) · n
✔ Do you want to install this sample project's dependencies with npm (hardhat @nomicfoundation/hardhat-toolbox)? (Y/n) · y
The standard Hardhat project comes with a pre-created
Lock.sol
contract and deploy.ts
script. You should clean up your working environment before moving forward:rm -f ./contracts/Lock.sol ./scripts/deploy.ts ./test/Lock.ts
Your folder files will look like this:

hardhat folder
In order to get started deploying new contracts on XDC Mainnet and/or Apothem, we need to install a new dependency called
dotenv
that will be used in the hardhat.config.ts
file:npm install --save-dev dotenv
You will need to configure a
.env
file with XDC Mainnet and Apothem Testnet RPC endpoints, plus the Private Key of the wallet we are using for deployment. Lets start by running:touch .env
Next, write the following info in your .env file:
XINFIN_NETWORK_URL=https://erpc.xinfin.network
APOTHEM_NETWORK_URL=https://erpc.apothem.network
PRIVATE_KEY=202e3c9d30bbeca38d6578659919d4c3dc989ae18c16756690877fdc4dfa607f
🚨 Do not use the Private Key in the example above in production or you can risk losing your assets! 🚨
Finally, we can configure the
hardhat.config.ts
file for both Apothem and XinFin Networks by writting:import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import * as dotenv from "dotenv";
dotenv.config();
const config: HardhatUserConfig = {
solidity: "0.8.17",
networks: {
xinfin: {
url: process.env.XINFIN_NETWORK_URL,
accounts: [process.env.PRIVATE_KEY!]
},
apothem: {
url: process.env.APOTHEM_NETWORK_URL,
accounts: [process.env.PRIVATE_KEY!]
}
}
};
export default config;
Now check your Signer's address on Hardhat by accessing the Hardhat console:
npx hardhat console --network xinfin
If you get an error that hardhat is not installed locally and are running on a Windows OS, you will need to execute:
npm install --save-dev @nomicfoundation/hardhat-toolbox
Once the hardhat console CLI opens, you can run:
> const hre = require("hardhat");
// Should log: Undefined
> const [owner] = await ethers.getSigners();
// Should log: Undefined
> owner.address
// Should log: '0xA4e66f4Cc17752f331eaC6A20C00756156719519' or your wallet address if you are using a different Private Key
This account is on the Ethereum standard format starting with
0x
, but you can simply switch 0x
for xdc
. In this example, our signer wallet address is: xdcA4e66f4Cc17752f331eaC6A20C00756156719519
.With this account in hand, we can head to the Apothem Faucet and claim some TXDC for development purposes:

Step 02
The source code for the XRC20 token used in this tutorial is available here: XRC20 Contract Folder. But we will address all
Events
, Methods
, and Constants
mentioned in the section 📰 About XRC20 Tokens.Start by creating the
XRC20.sol
file:touch ./contracts/XRC20.sol
Write the shell of your smart contract as shown here:
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
/**
* @title XRC20 Token
* @dev This is the a XinFin Network Compatible XRC20 token.
*/
contract XRC20Token {
}
Inside
contract XRC20Token
, you will instantiate name
, symbol
and decimals
as public variables, as well as a private _totalSupply
that will be used on our totalSupply()
method later on. You will also have two mapping variables, balances
and allowances
, which are key/value variables that maps user balances and approved spending allowances to other users:// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
/**
* @title XRC20 Token
* @dev This is the a XinFin Network Compatible XRC20 token.
*/
contract XRC20Token {
string public name;
string public symbol;
uint8 public decimals;
uint256 private _totalSupply;
mapping(address => uint) private balances;
mapping(address => mapping(address => uint)) private allowances;