RISE Logo-Light

Deploy an ERC20 Token

Create and deploy your own ERC20 token on RISE

Learn how to create and deploy your own ERC20 token on RISE using OpenZeppelin's battle-tested contracts.

What You'll Build

A standard ERC20 token with:

  • Custom name and symbol
  • Initial token supply
  • Standard transfer, approve, and allowance functions
  • Built on OpenZeppelin's secure implementation

The Contract

We'll use OpenZeppelin's ERC20 implementation:

MyToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

contract MyToken is ERC20 {
    constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }
}

This creates a token called "MyToken" with symbol "MTK" and mints the initial supply to the deployer.

Choose Your Tool

Deploy with Remix

The easiest way - no installation required!

Prerequisites

  • A Web3 wallet (MetaMask or Rabby) with RISE Testnet configured
  • Testnet ETH from the RISE Faucet

Open Remix IDE

Go to remix.ethereum.org in your browser.

Create the Contract

  1. In the File Explorer, create a new file: MyToken.sol
  2. Copy and paste this code:
MyToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

contract MyToken is ERC20 {
    constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }
}

Customize the token name ("MyToken") and symbol ("MTK") to your preference.

Compile

  1. Click the Solidity Compiler tab
  2. Select compiler version 0.8.20 or higher
  3. Click Compile MyToken.sol

Remix will automatically fetch the OpenZeppelin contracts from GitHub.

Deploy to RISE

  1. Click the Deploy & Run Transactions tab
  2. Select Injected Provider - MetaMask in Environment
  3. Connect your wallet when prompted
  4. Verify you're on RISE Testnet (Chain ID: 11155931)
  5. In the Contract dropdown, select MyToken
  6. Enter initial supply (e.g., 1000000 for 1 million tokens)
  7. Click Deploy
  8. Confirm the transaction in your wallet

Interact with Your Token

Under Deployed Contracts, you can:

  • Click name → Returns "MyToken"
  • Click symbol → Returns "MTK"
  • Click decimals → Returns 18
  • Click totalSupply → Returns total supply in wei (1000000 * 10^18)
  • Click balanceOf with your address → Shows your token balance

To transfer tokens:

  1. Expand the transfer function
  2. Enter recipient address and amount
  3. Click transact and confirm

View on Explorer

Visit RISE Testnet Explorer and search for your contract address to see all token transfers and holders.

Deploy with Foundry

Fast, Rust-based toolkit with OpenZeppelin integration.

Prerequisites

Create Project

Initialize a new Foundry project:

forge init erc20-token
cd erc20-token

Install OpenZeppelin Contracts

Install the OpenZeppelin contracts library:

forge install OpenZeppelin/openzeppelin-contracts

Configure remappings to make imports work:

forge remappings > remappings.txt

This creates a remappings.txt file that tells Foundry where to find OpenZeppelin contracts.

Create the Token Contract

Create src/MyToken.sol:

src/MyToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

contract MyToken is ERC20 {
    constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }
}

Configure RISE Network

Update foundry.toml:

foundry.toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.30"

[rpc_endpoints]
rise = "https://testnet.riselabs.xyz"

Compile

Build your contract:

forge build

Deploy

Deploy to RISE Testnet with 1 million token initial supply using your private key:

forge create \
  --rpc-url rise \
  --private-key 0xYOUR_PRIVATE_KEY_HERE \
  src/MyToken.sol:MyToken \
  --constructor-args 1000000

Alternatively, use a keystore for better security:

forge create \
  --rpc-url rise \
  --account <keystore-name> \
  src/MyToken.sol:MyToken \
  --constructor-args 1000000

Learn how to create a keystore: Foundry Keystore Guide

Save the contract address from the output!

Interact with Your Token

Check token name:

cast call <CONTRACT_ADDRESS> "name()" --rpc-url rise

Check your balance:

cast call <CONTRACT_ADDRESS> "balanceOf(address)(uint256)" <YOUR_ADDRESS> --rpc-url rise

Transfer tokens to another address:

cast send <CONTRACT_ADDRESS> \
  "transfer(address,uint256)" \
  <RECIPIENT_ADDRESS> \
  1000000000000000000 \
  --rpc-url rise \
  --private-key 0xYOUR_PRIVATE_KEY_HERE

Note: The amount is in wei (18 decimals), so 1000000000000000000 = 1 token.

View on Explorer

Visit RISE Testnet Explorer and search for your contract address.

Deploy with Hardhat

Flexible development environment with OpenZeppelin support.

Prerequisites

  • Node.js v22 or later
  • Testnet ETH from the RISE Faucet

Create Project

Initialize a new Hardhat project:

mkdir erc20-token
cd erc20-token
npm init -y
npm install --save-dev hardhat
npx hardhat --init

Select:

  • "Hardhat 3 Beta"
  • Current directory
  • "A minimal Hardhat project"
  • Install dependencies: yes

Install OpenZeppelin Contracts

Install the OpenZeppelin contracts package:

npm install @openzeppelin/contracts

Create the Token Contract

Create contracts/MyToken.sol:

mkdir contracts
contracts/MyToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

contract MyToken is ERC20 {
    constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }
}

Configure RISE Network

Update hardhat.config.ts:

hardhat.config.ts
import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem";
import { configVariable, defineConfig } from "hardhat/config";

export default defineConfig({
  plugins: [hardhatToolboxViemPlugin],
  solidity: {
    version: "0.8.30",
  },
  networks: {
    riseTestnet: {
      type: "http",
      url: "https://testnet.riselabs.xyz",
      accounts: [configVariable("RISE_PRIVATE_KEY")],
      chainId: 11155931
    }
  }
});

Set Your Private Key

Store your private key securely:

npx hardhat keystore set RISE_PRIVATE_KEY

Enter your private key when prompted.

Compile

Compile your contract:

npx hardhat compile

Create Deployment Module

Create the deployment script:

mkdir -p ignition/modules
ignition/modules/MyToken.ts
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";

export default buildModule("MyTokenModule", (m) => {
  const initialSupply = m.getParameter("initialSupply", 1000000n);

  const myToken = m.contract("MyToken", [initialSupply]);

  return { myToken };
});

Deploy

Deploy to RISE Testnet:

npx hardhat ignition deploy ignition/modules/MyToken.ts --network riseTestnet

To deploy with a custom initial supply:

npx hardhat ignition deploy ignition/modules/MyToken.ts --network riseTestnet --parameters '{"MyTokenModule":{"initialSupply":"5000000"}}'

Save the contract address from the output!

Interact with Your Token

Use Hardhat console:

npx hardhat console --network riseTestnet

Then in the console:

const MyToken = await ethers.getContractFactory("MyToken");
const token = await MyToken.attach("YOUR_CONTRACT_ADDRESS");

// Check name and symbol
await token.name();    // "MyToken"
await token.symbol();  // "MTK"

// Check total supply
await token.totalSupply();

// Check your balance
await token.balanceOf("YOUR_ADDRESS");

// Transfer tokens
await token.transfer("RECIPIENT_ADDRESS", ethers.parseUnits("100", 18));

View on Explorer

Visit RISE Testnet Explorer and search for your contract address.

Customizing Your Token

Change Token Details

Modify the constructor in your contract:

constructor(uint256 initialSupply) ERC20("YourTokenName", "YTN") {
    _mint(msg.sender, initialSupply * 10 ** decimals());
}

Add Minting Capability

Want to mint more tokens later? Add Ownable:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

contract MyToken is ERC20, Ownable {
    constructor(uint256 initialSupply) ERC20("MyToken", "MTK") Ownable(msg.sender) {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }
}

Add Burning Capability

Allow token holders to burn their tokens:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";

contract MyToken is ERC20, ERC20Burnable {
    constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
        _mint(msg.sender, initialSupply * 10 ** decimals());
    }
}

Next Steps