# How to Test AiToEarn Smart Contracts: A Complete Hardhat Implementation Guide

> Learn how to test AiToEarn smart contracts with Hardhat. This guide covers environment setup, contract integration, and TypeScript test execution using Ethers.js and Chai for robust validation.

- Repository: [yikart/AiToEarn](https://github.com/yikart/AiToEarn)
- Tags: tutorial
- Published: 2026-05-12

---

**Testing AiToEarn smart contracts requires initializing a Hardhat environment within the `project/aitoearn-backend` workspace, writing Solidity contracts to the `contracts/` directory, and executing TypeScript test suites powered by Ethers.js and Chai assertions.**

The AiToEarn repository is architected as an Nx monorepo utilizing pnpm workspaces, with core backend functionality located in `project/aitoearn-backend`. While the platform does not currently ship with native Solidity source code, comprehensive smart contract testing can be implemented by integrating Hardhat directly into this existing backend infrastructure.

## Setting Up the Hardhat Environment

Begin by ensuring your local machine runs **Node.js (≥ 18)** and has **pnpm** installed. From the repository root, install all dependencies:

```bash
pnpm install

```

Navigate to the backend workspace to initialize Hardhat:

```bash
cd project/aitoearn-backend
pnpm exec hardhat init

```

Configure environment variables for testnet or local blockchain access. Create an `.env` file based on the provided `.env.example` template:

```bash
RPC_URL=https://your-testnet-rpc.com
PRIVATE_KEY=your_private_key_here

```

This configuration enables secure deployment and testing without hardcoding sensitive credentials into source control.

## Writing Solidity Contracts

Place your smart contract source files in a `contracts/` directory within the backend workspace. The following example implements a simplified `AiToEarn` contract with core earning and withdrawal functionality:

```solidity
// contracts/AiToEarn.sol
pragma solidity ^0.8.20;

contract AiToEarn {
    address public owner;
    mapping(address => uint256) public balances;

    event Earned(address indexed user, uint256 amount);

    constructor() {
        owner = msg.sender;
    }

    function earn(uint256 amount) external {
        balances[msg.sender] += amount;
        emit Earned(msg.sender, amount);
    }

    function withdraw(uint256 amount) external {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        balances[msg.sender] -= amount;
        payable(msg.sender).transfer(amount);
    }
}

```

This contract demonstrates state management through the `balances` mapping and enforces access control via the `owner` variable initialized in the constructor.

## Developing Unit Tests with TypeScript

Create test files in [`test/AiToEarn.test.ts`](https://github.com/yikart/AiToEarn/blob/main/test/AiToEarn.test.ts) using Hardhat's built-in Ethers.js integration. The following test suite validates deployment, earning mechanics, and withdrawal constraints:

```typescript
// test/AiToEarn.test.ts
import { ethers } from "hardhat";
import { expect } from "chai";

describe("AiToEarn Contract", () => {
  let contract: any;
  let owner: any;
  let alice: any;

  beforeEach(async () => {
    [owner, alice] = await ethers.getSigners();
    const AiToEarn = await ethers.getContractFactory("AiToEarn");
    contract = await AiToEarn.deploy();
    await contract.waitForDeployment();
  });

  it("should initialize owner to deployer", async () => {
    expect(await contract.owner()).to.equal(owner.address);
  });

  it("should allow users to earn points", async () => {
    await contract.connect(alice).earn(100);
    expect(await contract.balances(alice.address)).to.equal(100);
  });

  it("should process withdrawals and deduct balances", async () => {
    await contract.connect(alice).earn(200);
    await contract.connect(alice).withdraw(150);
    expect(await contract.balances(alice.address)).to.equal(50);
  });

  it("should revert on insufficient balance withdrawals", async () => {
    await contract.connect(alice).earn(50);
    await expect(contract.connect(alice).withdraw(100))
      .to.be.revertedWith("Insufficient balance");
  });
});

```

The `beforeEach` hook ensures test isolation by deploying a fresh contract instance for every test case. The `connect()` method simulates transactions from specific signer accounts.

## Executing Tests Locally

Run the complete test suite from the backend workspace:

```bash
pnpm exec hardhat test

```

For integration testing against a persistent local network, start a Hardhat node in a separate terminal:

```bash
pnpm exec hardhat node

```

Then execute tests targeting the localhost network:

```bash
pnpm exec hardhat test --network localhost

```

Test output displays pass/fail status for each assertion, with detailed revert messages when transactions fail.

## Integrating Tests into CI/CD

Automate contract testing within the existing GitHub Actions workflow. Modify [`.github/workflows/backend-build.yml`](https://github.com/yikart/AiToEarn/blob/main/.github/workflows/backend-build.yml) to include Hardhat execution:

```yaml
- name: Run Hardhat tests
  run: |
    cd project/aitoearn-backend
    pnpm exec hardhat test

```

This ensures every pull request validates smart contract logic against the test suite before merging, maintaining code quality across the monorepo.

## Advanced Testing Strategies

**Forked Mainnet Testing**: Configure [`hardhat.config.ts`](https://github.com/yikart/AiToEarn/blob/main/hardhat.config.ts) to fork Ethereum mainnet state, enabling tests against real contract deployments without spending actual gas:

```typescript
networks: {
  hardhat: {
    forking: {
      url: process.env.RPC_URL,
      blockNumber: 18000000
    }
  }
}

```

**Gas Reporting**: Install `hardhat-gas-reporter` to analyze transaction costs per function call, optimizing contract efficiency before mainnet deployment.

**Oracle Mocking**: For contracts integrating Chainlink VRF or other oracles, use Hardhat's `mock` functionality to simulate callback data and test oracle-dependent logic deterministically.

## Summary

- **Initialize Hardhat** within `project/aitoearn-backend` to leverage the existing pnpm workspace infrastructure.
- **Store contracts** in a dedicated `contracts/` directory using Solidity ^0.8.20.
- **Write tests** in TypeScript using Ethers.js and Chai, validating state changes and revert conditions.
- **Execute locally** via `pnpm exec hardhat test` or against a running Hardhat node.
- **Automate validation** by adding Hardhat steps to [`.github/workflows/backend-build.yml`](https://github.com/yikart/AiToEarn/blob/main/.github/workflows/backend-build.yml).

## Frequently Asked Questions

### Does the AiToEarn repository include smart contract source code?

No, the AiToEarn repository focuses on application-layer code within an Nx monorepo structure. Smart contract testing requires creating a Hardhat project within the `project/aitoearn-backend` workspace and implementing Solidity contracts separately according to project requirements.

### Which testing frameworks are compatible with AiToEarn?

The backend workspace supports **Hardhat**, **Ethers.js**, and **Chai** through standard pnpm dependencies. This stack enables TypeScript-based testing with automated contract deployment, comprehensive assertion libraries, and native Hardhat network simulation capabilities.

### How do I configure automated testing in continuous integration?

Add a dedicated step to [`.github/workflows/backend-build.yml`](https://github.com/yikart/AiToEarn/blob/main/.github/workflows/backend-build.yml) that navigates to `project/aitoearn-backend` and executes `pnpm exec hardhat test`. This runs contract tests automatically on every commit and pull request, ensuring code reliability throughout the development lifecycle.

### Can I test against production blockchain state?

Yes, configure **forking** in [`hardhat.config.ts`](https://github.com/yikart/AiToEarn/blob/main/hardhat.config.ts) to target Ethereum mainnet or testnets using the RPC URL defined in your `.env` file. This allows testing against real-world state snapshots without deploying to production environments or spending actual gas.