Working with Celo Dollars (cUSD) and Celo Euro (cEUR)

Working with Celo Dollars (cUSD) and Celo Euro (cEUR)
none 0.0 0


In this article, we will explore how to interact with Celo’s native stablecoins, cUSD and cEUR, using Hardhat and a simple smart contract. We will also develop a decentralized application (dApp) to illustrate the principles involved.


  1. Basic understanding of blockchain and smart contracts.
  2. Familiarity with JavaScript and Solidity languages.
  3. Node.js and npm installed on your development environment.
  4. Metamask extension installed on your browser for interacting with the Celo network.
  5. Celo extension wallet installed on your browser.

Setting Up the Celo Development Environment

To start, create a new directory and navigate into it:

mkdir celo-dapp 
 cd celo-dapp

Next, initiate a new Node.js project:

npm init -y

Then, install Hardhat and other dependencies:

npm init --yes
npm install --save-dev hardhat
npm install --save-dev @nomicfoundation/hardhat-toolbox @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers
npm install express
npm install ejs

Next, create a Hardhat project:

npx hardhat
npm install @openzeppelin/contracts

Select “Create a JavaScript project” when prompted.

Smart Contract Development

We will create a simple contract named StablecoinWallet that interacts with the cUSD and cEUR stablecoin contracts on Celo.

Create a new file contracts/StablecoinWallet.sol and add the following:

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;  // Specifies the compiler version for Solidity

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";  // Imports the IERC20 interface from OpenZeppelin

// This is a contract for a StablecoinWallet that accepts Celo's cUSD and cEUR
contract StablecoinWallet {
    // Public address variables for the cUSD and cEUR tokens
    address public cUSDAddress;
    address public cEURAddress;

    // Constructor that sets the addresses of cUSD and cEUR when the contract is deployed
    constructor(address _cUSDAddress, address _cEURAddress) {
   	 cUSDAddress = _cUSDAddress;
   	 cEURAddress = _cEURAddress;

    // Function to deposit either cUSD or cEUR into the wallet
    function deposit(address token, uint amount) external {
   	 // Checks if the token is either cUSD or cEUR, else it throws an "Invalid token" error
   	 require(token == cUSDAddress || token == cEURAddress, "Invalid token");
   	 // Attempts to transfer the tokens from the sender to this contract. If the transfer fails, it throws a "Transfer failed" error
   	 require(IERC20(token).transferFrom(msg.sender, address(this), amount), "Transfer failed");

    // Function to check the balance of either cUSD or cEUR in the wallet
    function balanceOf(address token) external view returns (uint) {
   	 // Returns the balance of the specified token in the wallet
   	 return IERC20(token).balanceOf(address(this));

This contract has two functions: deposit() and balanceOf(). The deposit() function allows users to deposit cUSD or cEUR into the contract. The balanceOf() function allows anyone to check the balance of cUSD or cEUR that the contract holds.

Compile your contract

npx hardhat compile


Deploying the Smart Contract

Before deploying the contract, we need to set up Hardhat for Celo. In the hardhat.config.js file, add the following:


// Add the alfajores network to the configuration
module.exports = {
  solidity: "0.8.17",
  networks: {
    alfajores: {
      url: "",
      accounts: {
        mnemonic: "taxi expire enforce produce expire second pottery come knee fold slab yard",
        path: "m/44'/52752'/0'/0",
      chainId: 44787,

To deploy the contract, create a new script scripts/deploy.js:

// Declare an asynchronous function named 'main'.
async function main() {
	// Get the account that will deploy the contracts, called the 'deployer'.
	const [deployer] = await ethers.getSigners();

	// Log the Ethereum address of the deployer account to the console.
   	 "Deploying contracts with the account:",

	// Get the contract factory for the 'StablecoinWallet' contract.
	const StablecoinWallet = await ethers.getContractFactory("StablecoinWallet");

	// Deploy a new instance of the 'StablecoinWallet' contract, initializing it with the
	// addresses of the Celo Dollar and Celo Euro contracts.
	const stablecoinWallet = await StablecoinWallet.deploy(

	// Log the Ethereum address of the newly deployed 'StablecoinWallet' contract to the console.
	console.log("StablecoinWallet contract address:", stablecoinWallet.address);

// Call the main function. If the promise it returns is fulfilled, then exit the process with a
// status code of 0, indicating success. If the promise is rejected (i.e., an error occurs), then
// log the error to the console and exit the process with a status code of 1, indicating failure.
	.then(() => process.exit(0))
	.catch((error) => {

You can now deploy your contract with the command:

npx hardhat run scripts/deploy.js --network alfajores


Creating a dApp

Now, we will create a dApp that interacts with our deployed contract and Celo’s cUSD and cEUR. For simplicity, this dApp will display the balance of cUSD and cEUR in our contract.

First, create a new index.ejs file in the views directory with the following content:

<!DOCTYPE html>
    <title>Celo Stablecoin Balances</title>
          body {
              font-family: Arial, sans-serif;
              background-color: #F3F3F3;
              padding: 50px;
              color: #333;
          h1 {
              text-align: center;
              color: #007BFF;
          h2 {
              text-align: center;
              margin-top: 40px;
    <div class="container">
        <h1>Celo Stablecoin Balances</h1>
        <p id="cUSDBalance">cUSD Balance: <%= cUSD %></p>
        <p id="cEURBalance">cEUR Balance: <%= cEUR %></p>

Next, create a new index.js file in the project root directory with the following content:

const express = require('express');
const app = express();
const path = require('path');

// Set the view engine to EJS
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));

app.get('/', async function(req, res) {
    // Retrieve the balances from your contract (replace with your own logic)
    const cUSDBalance = '1000 cUSD';
    const cEURBalance = '500 cEUR';

    // Render the EJS template with the balance data
    res.render('index', { cUSD: cUSDBalance, cEUR: cEURBalance });

app.listen(3001, function() {
    console.log('Server started on port 3001');

Finally, in the terminal, navigate to your project directory and run the following command to start the server:

node index.js

Now, you can access your dApp by opening your browser and navigating to http://localhost:3001.


Remember to replace '0xYourCeloDollarContractAddress' and '0xYourCeloEuroContractAddress' with the actual addresses of your deployed cUSD and cEUR contracts.


In this article, we’ve explored how to interact with Celo’s native stablecoins, cUSD and cEUR, within a dApp and a smart contract using Hardhat. We’ve covered setting up a Celo development environment, creating a smart contract that interacts with cUSD and cEUR, deploying the contract, and developing a simple dApp using EJS to display the balances.

About the Author

I’m a Web3 fullstack developer and technical writer. You can connect with me on GitHub, Twitter, Linkedin.


Celo Documentation
Source Code


This appears to be a tutorial rather than a pathway. Removing the pathway tag.

1 Like

Congratulations on being among the highest voted proposals for this week! I’m moving this to todo so that you can get started on this project. :mortar_board: :seedling:

1 Like

Hey @Jorshimayor I will be reviewing this in a day or two

1 Like

Hey is it possible , you can deploy it in vercel and the can attach the link, because this is kind of article where people would like to see it in action, or try to add the screenshot of your web page, which you have created with the help of html, waiting for you, good piece here bro @Jorshimayor


1 Like

Thanks for your suggestion Ishan, I’ll make the adjustment asap.

1 Like

Hi, kindly check the edits I made Ishan. Thanks


Hi @ishan.pathak2711 , any updates?