# Deploy an ERC20 Token (/docs/cookbook/deploy-erc20-token)

import { Step, Steps } from 'fumadocs-ui/components/steps';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

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:

```solidity title="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

<Tabs items={['Remix', 'Foundry', 'Hardhat']}>
  <Tab value="Remix">
    ## 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](https://faucet.testnet.riselabs.xyz/)

    <Steps>
      <Step>
        ### Open Remix IDE

        Go to [remix.ethereum.org](https://remix.ethereum.org) in your browser.
      </Step>

      <Step>
        ### Create the Contract

        1. In the File Explorer, create a new file: `MyToken.sol`
        2. Copy and paste this code:

        ```solidity title="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());
            }
        }
        ```

        <Callout type="info">
          Customize the token name ("MyToken") and symbol ("MTK") to your preference.
        </Callout>
      </Step>

      <Step>
        ### 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.
      </Step>

      <Step>
        ### 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
      </Step>

      <Step>
        ### 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
      </Step>
    </Steps>

    ### View on Explorer

    Visit [RISE Testnet Explorer](https://explorer.testnet.riselabs.xyz) and search for your contract address to see all token transfers and holders.
  </Tab>

  <Tab value="Foundry">
    ## Deploy with Foundry

    Fast, Rust-based toolkit with OpenZeppelin integration.

    ### Prerequisites

    * Foundry installed ([installation guide](https://book.getfoundry.sh/getting-started/installation))
    * Testnet ETH from the [RISE Faucet](https://faucet.testnet.riselabs.xyz/)

    <Steps>
      <Step>
        ### Create Project

        Initialize a new Foundry project:

        ```bash
        forge init erc20-token
        cd erc20-token
        ```
      </Step>

      <Step>
        ### Install OpenZeppelin Contracts

        Install the OpenZeppelin contracts library:

        ```bash
        forge install OpenZeppelin/openzeppelin-contracts
        ```

        Configure remappings to make imports work:

        ```bash
        forge remappings > remappings.txt
        ```

        This creates a `remappings.txt` file that tells Foundry where to find OpenZeppelin contracts.
      </Step>

      <Step>
        ### Create the Token Contract

        Create `src/MyToken.sol`:

        ```solidity title="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());
            }
        }
        ```
      </Step>

      <Step>
        ### Configure RISE Network

        Update `foundry.toml`:

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

        [rpc_endpoints]
        rise = "https://testnet.riselabs.xyz"
        ```
      </Step>

      <Step>
        ### Compile

        Build your contract:

        ```bash
        forge build
        ```
      </Step>

      <Step>
        ### Deploy

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

        ```bash
        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:

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

        <Callout type="info">
          Learn how to create a keystore: [Foundry Keystore Guide](https://book.getfoundry.sh/reference/cast/cast-wallet-import)
        </Callout>

        Save the contract address from the output!
      </Step>

      <Step>
        ### Interact with Your Token

        Check token name:

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

        Check your balance:

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

        Transfer tokens to another address:

        ```bash
        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.
      </Step>
    </Steps>

    ### View on Explorer

    Visit [RISE Testnet Explorer](https://explorer.testnet.riselabs.xyz) and search for your contract address.
  </Tab>

  <Tab value="Hardhat">
    ## Deploy with Hardhat

    Flexible development environment with OpenZeppelin support.

    ### Prerequisites

    * Node.js v22 or later
    * Testnet ETH from the [RISE Faucet](https://faucet.testnet.riselabs.xyz/)

    <Steps>
      <Step>
        ### Create Project

        Initialize a new Hardhat project:

        ```bash
        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
      </Step>

      <Step>
        ### Install OpenZeppelin Contracts

        Install the OpenZeppelin contracts package:

        ```bash
        npm install @openzeppelin/contracts
        ```
      </Step>

      <Step>
        ### Create the Token Contract

        Create `contracts/MyToken.sol`:

        ```bash
        mkdir contracts
        ```

        ```solidity title="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());
            }
        }
        ```
      </Step>

      <Step>
        ### Configure RISE Network

        Update `hardhat.config.ts`:

        ```typescript title="hardhat.config.ts" {2,11-16}
        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
            }
          }
        });
        ```
      </Step>

      <Step>
        ### Set Your Private Key

        Store your private key securely:

        ```bash
        npx hardhat keystore set RISE_PRIVATE_KEY
        ```

        Enter your private key when prompted.
      </Step>

      <Step>
        ### Compile

        Compile your contract:

        ```bash
        npx hardhat compile
        ```
      </Step>

      <Step>
        ### Create Deployment Module

        Create the deployment script:

        ```bash
        mkdir -p ignition/modules
        ```

        ```typescript title="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 };
        });
        ```
      </Step>

      <Step>
        ### Deploy

        Deploy to RISE Testnet:

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

        To deploy with a custom initial supply:

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

        Save the contract address from the output!
      </Step>

      <Step>
        ### Interact with Your Token

        Use Hardhat console:

        ```bash
        npx hardhat console --network riseTestnet
        ```

        Then in the console:

        ```javascript
        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));
        ```
      </Step>
    </Steps>

    ### View on Explorer

    Visit [RISE Testnet Explorer](https://explorer.testnet.riselabs.xyz) and search for your contract address.
  </Tab>
</Tabs>

## Customizing Your Token

### Change Token Details

Modify the constructor in your contract:

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

### Add Minting Capability

Want to mint more tokens later? Add Ownable:

```solidity
// 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:

```solidity
// 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

<Cards>
  <Card title="OpenZeppelin Contracts" href="https://docs.openzeppelin.com/contracts" description="Learn about all OpenZeppelin contract features" />

  <Card title="ERC20 Standard" href="https://eips.ethereum.org/EIPS/eip-20" description="Read the official ERC20 specification" />

  <Card title="Frontend Integration" href="/docs/builders/frontend" description="Connect your token to a web interface" />
</Cards>
