How to Write and Deploy a Simple Stablecoin on Linea

Learn how to write and deploy your own stablecoin on the Linea network

by Sushmita RashidSeptember 19, 2024
How to Write and Deploy a Simple Stablecoin on Linea image

Stablecoins have become a key part of the blockchain and web3 ecosystem, helping users avoid the volatility of cryptocurrencies like Bitcoin and Ethereum. In this blog, we’ll learn what stablecoins are and how to write a simple stablecoin contract. In this blog, we’ll learn what stablecoins are and how to write and deploy a simple stablecoin contract on Linea.

What are stablecoins?

Stablecoins are a type of cryptocurrency designed to keep its value steady. They do this by pegging their value to something more stable, like a traditional currency, such as the US dollar, a commodity like gold, or even another cryptocurrency. The goal of stablecoins is to combine the advantages of cryptocurrencies—such as fast transactions and decentralization—with the stability of traditional financial assets, making them more reliable and useful for everyday transactions.

stablecoins can be classified based on several factors, including their collateral structure, stability mechanism, and relative stability. Here's a comprehensive breakdown of stablecoin types:

1. Fiat-collateralized stablecoins

Traditional currencies back fiat-collateralized stablecoins like the US dollar or Euro, held in reserves (e.g., Tether USDT, USD Coin USDC). Since they're directly tied to fiat, they are stable and easy to use. However, they rely on centralized entities for reserves and face regulatory oversight.

2. Crypto-collateralized stablecoins

Crypto-collateralized stablecoins, like DAI and LUSD, are backed by other cryptocurrencies and are often over-collateralized to handle crypto’s volatility. They are more decentralized than fiat-backed options. However, they're complex and can be less stable during market downturns, requiring active management to maintain stability.

3. Algorithmic stablecoins

Algorithmic stablecoins, such as Ampleforth (AMPL), rely on algorithms to adjust supply and stabilize prices without direct collateral. While highly decentralized and flexible, they are difficult to understand and can be vulnerable to rapid loss of value ("death spirals") if confidence drops.

There are also a few others, like hybrid stablecoins such as Frax (FRAX), which combine collateral and algorithmic methods to achieve stability, offering a balance of different models but with added complexity. Commodity-backed stablecoins, like Paxos Gold (PAXG), are tied to physical assets, providing digital exposure to real-world commodities. Yield-bearing stablecoins, such as Compound USD (cUSD), generate returns through lending or investments, offering passive income but with higher associated risks.

Now that we understand stablecoins and the types of stablecoins in the ecosystem today let’s explore how to create a stablecoin on the Linea network.

Set up the development environment

The first step is to ensure your environment is set up properly:

  • Install Node.js and npm (Node package manager).

  • Install Hardhat by running:

npm install --save-dev hardhat

Create a new Hardhat project

In your project directory, initialize a new Hardhat project:

npx hardhat init

We’ll use TypeScript for this tutorial, as Hardhat already has all the necessary dependencies for you. After initialization, you'll have a project structure that includes:

  • contracts/: Solidity contracts
  • ignition/: Ignition deployment modules
  • test/: Test files
  • hardhat.config.js: Hardhat configuration

Now, let’s dive into writing our own stablecoin contract for the RadStablecoin (RAD). This will be a simple Ethereum-collateralized stablecoin with a 150% collateralization ratio.

In this contract:

  • ETH will be used as collateral.
  • A 150% collateralization ratio will ensure stability.
  • Users can mint stablecoins by sending ETH and burn them to reclaim their collateral.
  • A simple price oracle will be used to fetch the price of ETH (in a real-world scenario, you’d use a secure decentralized oracle).
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/// @title RadStablecoin
/// @notice A simple stablecoin implementation with collateral-based minting
/// @dev Inherits from ERC20 and Ownable
contract RadStablecoin is ERC20, Ownable {
    /// @notice The collateralization ratio (150%)
    uint256 public constant COLLATERAL_RATIO = 150;

    /// @notice The precision for price calculations (2 decimal places)
    uint256 public constant PRICE_PRECISION = 100;

    /// @notice Mapping to track collateral balances for each user
    mapping(address => uint256) public collateralBalances;

    /// @notice Initializes the RadStablecoin contract
    constructor() ERC20("RadStablecoin", "RAD") {}

    /// @notice Allows users to deposit LineaETH as collateral
    /// @dev The deposited amount is added to the user's collateral balance
    function depositCollateral() external payable {
        collateralBalances[msg.sender] += msg.value;
    }

    /// @notice Allows users to withdraw their deposited collateral
    /// @dev Implements the checks-effects-interactions pattern to prevent reentrancy
    /// @param amount The amount of collateral to withdraw (in wei)
    function withdrawCollateral(uint256 amount) external {
        require(collateralBalances[msg.sender] >= amount, "Insufficient collateral");
        collateralBalances[msg.sender] -= amount; // Update state before making external call
        payable(msg.sender).transfer(amount);     // Safely transfer LineaETH after updating state
    }

    /// @notice Mints stablecoin (RAD) based on the user's deposited collateral
    /// @dev Calculates required collateral based on current LineaETH price and mints RAD tokens
    /// @param stablecoinAmount The amount of stablecoin to mint
    function mintStablecoin(uint256 stablecoinAmount) external {
        uint256 collateralRequired = (stablecoinAmount * COLLATERAL_RATIO * PRICE_PRECISION) / (100 * getCurrentPrice());
        require(collateralBalances[msg.sender] >= collateralRequired, "Insufficient collateral");

        collateralBalances[msg.sender] -= collateralRequired;
        _mint(msg.sender, stablecoinAmount);
    }

    /// @notice Burns stablecoin (RAD) and returns the equivalent collateral to the user
    /// @dev Calculates collateral to return based on current LineaETH price and burns RAD tokens
    /// @param stablecoinAmount The amount of stablecoin to burn
    function burnStablecoin(uint256 stablecoinAmount) external {
        require(balanceOf(msg.sender) >= stablecoinAmount, "Insufficient stablecoin balance");

        uint256 collateralToReturn = (stablecoinAmount * COLLATERAL_RATIO * PRICE_PRECISION) / (100 * getCurrentPrice());
        _burn(msg.sender, stablecoinAmount);
        collateralBalances[msg.sender] += collateralToReturn;
    }

    /// @notice Gets the current price of LineaETH in USD
    /// @dev In a real-world scenario, this would fetch the price from an oracle
    /// @return The current LineaETH price in USD (fixed at $2000 for simplicity)
    function getCurrentPrice() public view returns (uint256) {
        // In a real-world scenario, this would fetch the current LineaETH/USD price from an oracle
        // For simplicity, we'll use a fixed price of $2000 per LineaETH
        return 200000; // $2000.00
    }
}
  1. Collateral Management:
    • Depositing Collateral:
      • Users can deposit Ether (ETH) as collateral by calling depositCollateral.
      • The deposited ETH is stored in the collateralBalances mapping, tracking total collateral for users.
    • Withdrawing Collateral:
      • Users can withdraw their collateral using withdrawCollateral.
  2. Stablecoin Operations:
    • Minting Stablecoins:
      • The mintStablecoin function ensures that the user has sufficient collateral to mint the requested amount of RAD tokens.
    • Burning Stablecoins:
      • The burnStablecoin function burns the specified amount of RAD and returns the equivalent amount of ETH based on the 150% collateralization ratio and the current price of ETH.
  3. Price Feeds:
    • Fetching the Price of ETH:
      • The contract includes a function getCurrentPrice that returns a fixed price of $2000 for ETH in this simplified example.

Configure Hardhat for Linea

Update your hardhat.config.js to include the Linea testnet configuration. Add the following network configuration:

import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import * as dotenv from "dotenv";

dotenv.config();

const config: HardhatUserConfig = {
  solidity: "0.8.24",
  networks: {
    "linea-testnet": {
      url: `https://linea-sepolia.infura.io/v3/${process.env.INFURA_API_KEY}`,
      accounts: [process.env.ACCOUNT_PRIVATE_KEY!],
    },
  },
};
export default config;

Create the deployment script

In the ignition/modules/ directory, create a file called RadStablecoin.ts and include the following script:

import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";

const RadStablecoinModule = buildModule("RadStablecoinModule", (m) => {
  // Deploy the RadStablecoin contract
  const radStablecoin = m.contract("RadStablecoin");

  // Return the deployed contract instance
  return { radStablecoin };
});

export default RadStablecoinModule;

To compile the contract run the following command:

npx hardhat compile

Before deploying the smart contract, make sure to update the .env file in the directory with the following values:

# Infura API key for connecting to Ethereum networks
INFURA_API_KEY=your_infura_api_key_here

# Private key of the account to be used for deployments and transactions
ACCOUNT_PRIVATE_KEY=your_account_private_key_here

Deploy the contract

Finally, deploy the RadStablecoin contract to Linea:

npx hardhat ignition deploy ignition/modules/RadStablecoin.ts --network linea-testnet

This will deploy the marketplace smart contract on Linea Sepolia.

What next?

Stablecoins play a crucial role in the cryptocurrency ecosystem, offering much-needed stability for financial applications. In this tutorial, we explored the core concepts of stablecoins, their various types, and how they bridge traditional finance with decentralized technology. We also gained hands-on experience by creating and deploying RadStablecoin on the Linea network, deepening our understanding of collateral-backed stablecoins —happy coding!

Receive our Newsletter