Deploy on EVM (Hardhat)

Create a wallet using Metamask (see how to configure) and request funds from the faucet for your new account.

Once your account is funded, download Node.js:

Create a project

Let's create a project with Hardhat. Create a new folder and run the following command inside:

npm init --y
npm install --save-dev hardhat

The command will initialize a new npm project and install Hardhat locally.

Initialize a new Hardhat project

npx hardhat

Select TypeScript as the project type, and for the rest of the questions, such as .gitignore and sample project, choose y or yes

Configure Hardhat with Lumio

Open the hardhat.config.ts file generated by the previous command, and replace its content with the following:

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


const config: HardhatUserConfig = {
  solidity: "0.8.20",
  networks: {
    'lumio-testnet': {
      url: '',
      accounts: [process.env.WALLET_KEY as string],
      gasPrice: 3000000000,
  defaultNetwork: 'hardhat',

export default config;

Install toolbox

To install hardhat-toolbox, run the following command:

npm install --save-dev @nomicfoundation/hardhat-toolbox

Install dotenv

To install the dotenv dependency, use the following command:

npm install --save-dev dotenv

Once the dependency is installed, let's create a new file named .env and place the private key inside it:

export WALLET_KEY=<your private key>

See how to export your private key from Metamask.

ERC20 Contract

Let's deploy an ERC-20 contract on the testnet. First, navigate to the contracts/ folder and remove the Lock.sol file from the sample project as it is not needed.

Now, let's install the OpenZeppelin framework:

npm install --save @openzeppelin/contracts

Create a new file in the contracts/ directory and name it Token.sol . Then, put the following code inside:

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.20;

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

contract Token is ERC20 {
    uint constant _initial_supply = 100000000 * (10**18);
    constructor() ERC20("MyToken", "TOKEN") {
        _mint(msg.sender, _initial_supply);

Let's compile the code by running the following command:

npx hardhat compile

After successful compilation, let's deploy the contract. Open the scripts/deploy.ts file and replace its contents with the following code:

import { ethers } from "hardhat";

async function main() {
  const token = await ethers.deployContract('Token', { gasLimit: 1000000 });
  await token.waitForDeployment();
  console.log(`Token contract deployed at ${}`);

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  process.exitCode = 1;

Important: Reth L2 doesn't support the "block tag pending." So, in case you encounter issues with block tags while using Hardhat, try adding the parameter blockTag: "latest". This may be particularly relevant, especially when estimating gas.

For deploy run the following command:

npx hardhat run scripts/deploy.ts --network lumio-testnet

Awesome, after deployment you would see message:

Token contract deployed at <address>

Copy the address and go to block explorer, that's all! Now you can continue develop your contract/project on the EVM part of the L2.

Last updated