# "Architecting High-Performance DeFi Infrastructure on Injective inEVM"

*A deep dive into Tendermint BFT consensus, gas optimization, and production-grade deployment patterns*

By [Injective](https://paragraph.com/@kaptan_web3) · 2026-01-16

injective, solidity, defi, web3, ethereum

---

    # Zero to Hero: Deploying Your First ERC-20 Token on Injective inEVM with Hardhat
    
    > **TL;DR**: Hardhat + Injective inEVM = sub-second finality, EVM compatibility, and the tooling you already know. Ship faster.
    
    
    **Why Hardhat + Injective inEVM?**
    
    Injective's inEVM brings the entire Ethereum toolchain to a chain with **~1 second block times** and **instant finality**. No waiting for confirmations. No gas wars. Just deploy and iterate.
    
    Hardhat gives you:
    - Native TypeScript support
    - Built-in testing framework
    - Seamless contract verification
    - Plugin ecosystem (ethers.js, OpenZeppelin upgrades, etc.)
    
    **This is the stack for builders who ship.**
    
    
    **Prerequisites**
    
    ```bash
    node -v  # v18.0.0 or higher
    npm -v   # v9.0.0 or higher
    ```
    
    If you don't have Hardhat globally:
    ```bash
    npm install --save-dev hardhat
    ```
    
    
    **Project Setup**
    
    ```bash
    mkdir injective-token && cd injective-token
    npx hardhat init
    ```
    
    Select: **Create a JavaScript project**
    
    Install dependencies:
    ```bash
    npm install --save-dev @nomicfoundation/hardhat-toolbox
    npm install @openzeppelin/contracts
    ```
    
    
    **Configuration: hardhat.config.js**
    
    Replace your `hardhat.config.js` with:
    
    ```javascript
    require("@nomicfoundation/hardhat-toolbox");
    require("dotenv").config();
    
    /** @type import('hardhat/config').HardhatUserConfig */
    module.exports = {
      solidity: {
        version: "0.8.20",
        settings: {
          optimizer: {
            enabled: true,
            runs: 200,
          },
        },
      },
      networks: {
        injectiveTestnet: {
          url: "https://testnet.rpc.inevm.com",
          chainId: 2424,
          accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
          gasPrice: 500000000, // 0.5 gwei
        },
        injectiveMainnet: {
          url: "https://mainnet.rpc.inevm.com",
          chainId: 2525,
          accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
          gasPrice: 500000000,
        },
      },
      etherscan: {
        apiKey: {
          injectiveTestnet: "no-api-key-needed",
          injectiveMainnet: "no-api-key-needed",
        },
        customChains: [
          {
            network: "injectiveTestnet",
            chainId: 2424,
            urls: {
              apiURL: "https://testnet.explorer.inevm.com/api",
              browserURL: "https://testnet.explorer.inevm.com",
            },
          },
          {
            network: "injectiveMainnet",
            chainId: 2525,
            urls: {
              apiURL: "https://explorer.inevm.com/api",
              browserURL: "https://explorer.inevm.com",
            },
          },
        ],
      },
    };
    ```
    
    Create a `.env` file:
    ```bash
    PRIVATE_KEY=your_private_key_here_without_0x_prefix
    ```
    
    > ⚠️ **Never commit your `.env` file. Add it to `.gitignore`.**
    
    
    **The Contract: contracts/InjectiveToken.sol**
    
    ```solidity
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.20;
    
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
    import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
    import "@openzeppelin/contracts/access/Ownable.sol";
    
    /**
     * @title InjectiveToken
     * @dev Production-ready ERC-20 token for Injective inEVM
     * @notice Includes burn functionality and EIP-2612 permit for gasless approvals
     */
    contract InjectiveToken is ERC20, ERC20Burnable, ERC20Permit, Ownable {
        uint8 private immutable _decimals;
    
        /**
         * @dev Constructor that mints initial supply to deployer
         * @param name_ Token name
         * @param symbol_ Token symbol
         * @param decimals_ Token decimals (typically 18)
         * @param initialSupply_ Initial token supply (in whole tokens, not wei)
         */
        constructor(
            string memory name_,
            string memory symbol_,
            uint8 decimals_,
            uint256 initialSupply_
        ) ERC20(name_, symbol_) ERC20Permit(name_) Ownable(msg.sender) {
            _decimals = decimals_;
            _mint(msg.sender, initialSupply_ * 10 ** decimals_);
        }
    
        function decimals() public view virtual override returns (uint8) {
            return _decimals;
        }
    
        /**
         * @dev Allows owner to mint additional tokens
         * @param to Recipient address
         * @param amount Amount to mint (in wei)
         */
        function mint(address to, uint256 amount) public onlyOwner {
            _mint(to, amount);
        }
    }
    ```
    
    
    **Deployment Script: scripts/deploy.js**
    
    ```javascript
    const hre = require("hardhat");
    
    async function main() {
      const [deployer] = await hre.ethers.getSigners();
      
      console.log("Deploying contracts with account:", deployer.address);
      console.log("Account balance:", (await deployer.provider.getBalance(deployer.address)).toString());
    
      // Token parameters
      const TOKEN_NAME = "Injective Builder Token";
      const TOKEN_SYMBOL = "IBT";
      const TOKEN_DECIMALS = 18;
      const INITIAL_SUPPLY = 1_000_000; // 1 million tokens
    
      console.log("\n📦 Deploying InjectiveToken...");
      
      const InjectiveToken = await hre.ethers.getContractFactory("InjectiveToken");
      const token = await InjectiveToken.deploy(
        TOKEN_NAME,
        TOKEN_SYMBOL,
        TOKEN_DECIMALS,
        INITIAL_SUPPLY
      );
    
      await token.waitForDeployment();
      const tokenAddress = await token.getAddress();
    
      console.log("\n✅ InjectiveToken deployed successfully!");
      console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
      console.log("Contract Address:", tokenAddress);
      console.log("Token Name:", TOKEN_NAME);
      console.log("Token Symbol:", TOKEN_SYMBOL);
      console.log("Total Supply:", INITIAL_SUPPLY.toLocaleString(), TOKEN_SYMBOL);
      console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
      
      console.log("\n🔍 View on Explorer:");
      console.log(`https://testnet.explorer.inevm.com/address/${tokenAddress}`);
    
      // Return deployment info for verification
      return {
        address: tokenAddress,
        constructorArgs: [TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS, INITIAL_SUPPLY],
      };
    }
    
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    ```
    
    
    **Deploy to Injective Testnet**
    
    **1. Get Testnet INJ**
    
    Fund your wallet with testnet INJ from the [Injective Faucet](https://testnet.faucet.injective.network/).
    
    **2. Compile**
    
    ```bash
    npx hardhat compile
    ```
    
    **3. Deploy**
    
    ```bash
    npx hardhat run scripts/deploy.js --network injectiveTestnet
    ```
    
    Expected output:
    ```
    Deploying contracts with account: 0xYourAddress
    Account balance: 1000000000000000000
    
    📦 Deploying InjectiveToken...
    
    ✅ InjectiveToken deployed successfully!
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    Contract Address: 0xDeployedContractAddress
    Token Name: Injective Builder Token
    Token Symbol: IBT
    Total Supply: 1,000,000 IBT
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    🔍 View on Explorer:
    https://testnet.explorer.inevm.com/address/0xDeployedContractAddress
    ```
    
    
    **Contract Verification**
    
    Verify your contract on the Injective Explorer:
    
    ```bash
    npx hardhat verify --network injectiveTestnet \
      DEPLOYED_CONTRACT_ADDRESS \
      "Injective Builder Token" \
      "IBT" \
      18 \
      1000000
    ```
    
    Replace `DEPLOYED_CONTRACT_ADDRESS` with your actual contract address.
    
    **Manual Verification (Alternative)**
    
    If automated verification fails:
    
    1. Go to [Injective Testnet Explorer](https://testnet.explorer.inevm.com)
    2. Search for your contract address
    3. Click "Verify & Publish"
    4. Select:
       - Compiler: `0.8.20`
       - Optimization: `Yes (200 runs)`
       - License: `MIT`
    5. Flatten your contract:
       ```bash
       npx hardhat flatten contracts/InjectiveToken.sol > Flattened.sol
       ```
    6. Paste the flattened code and submit
    
    
    **Testing Your Token**
    
    Create `test/InjectiveToken.test.js`:
    
    ```javascript
    const { expect } = require("chai");
    const { ethers } = require("hardhat");
    
    describe("InjectiveToken", function () {
      let token;
      let owner;
      let addr1;
      
      const NAME = "Injective Builder Token";
      const SYMBOL = "IBT";
      const DECIMALS = 18;
      const INITIAL_SUPPLY = 1_000_000;
    
      beforeEach(async function () {
        [owner, addr1] = await ethers.getSigners();
        const InjectiveToken = await ethers.getContractFactory("InjectiveToken");
        token = await InjectiveToken.deploy(NAME, SYMBOL, DECIMALS, INITIAL_SUPPLY);
      });
    
      it("Should have correct name and symbol", async function () {
        expect(await token.name()).to.equal(NAME);
        expect(await token.symbol()).to.equal(SYMBOL);
      });
    
      it("Should mint initial supply to deployer", async function () {
        const expectedSupply = ethers.parseUnits(INITIAL_SUPPLY.toString(), DECIMALS);
        expect(await token.totalSupply()).to.equal(expectedSupply);
        expect(await token.balanceOf(owner.address)).to.equal(expectedSupply);
      });
    
      it("Should allow owner to mint", async function () {
        const mintAmount = ethers.parseUnits("1000", DECIMALS);
        await token.mint(addr1.address, mintAmount);
        expect(await token.balanceOf(addr1.address)).to.equal(mintAmount);
      });
    
      it("Should allow burning", async function () {
        const burnAmount = ethers.parseUnits("1000", DECIMALS);
        await token.burn(burnAmount);
        const expectedBalance = ethers.parseUnits((INITIAL_SUPPLY - 1000).toString(), DECIMALS);
        expect(await token.balanceOf(owner.address)).to.equal(expectedBalance);
      });
    });
    ```
    
    Run tests:
    ```bash
    npx hardhat test
    ```
    
    
    **Quick Reference**
    
    | Network | Chain ID | RPC URL | Explorer |
    |---------|----------|---------|----------|
    | Testnet | 2424 | https://testnet.rpc.inevm.com | https://testnet.explorer.inevm.com |
    | Mainnet | 2525 | https://mainnet.rpc.inevm.com | https://explorer.inevm.com |
    
    
    **What's Next?**
    
    You just deployed on **the fastest EVM chain**. Here's what you can build next:
    
    - 🔄 **DEX Integration**: List your token on Injective DEXs
    - 🌉 **Cross-chain Bridges**: Connect to Ethereum, Cosmos, Solana
    - 📊 **DeFi Protocols**: Build lending, staking, or yield protocols
    - 🎮 **Gaming/NFTs**: Leverage instant finality for gaming assets
    
    
    **Resources**
    
    - [Injective inEVM Docs](https://docs.injective.network/develop/guides/inEVM/)
    - [Hardhat Documentation](https://hardhat.org/docs)
    - [OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts)
    - [Injective Discord](https://discord.gg/injective)
    
    
    **Built with 🥷 for the Injective ecosystem.**

---

*Originally published on [Injective](https://paragraph.com/@kaptan_web3/injective)*
