> ## Documentation Index
> Fetch the complete documentation index at: https://sidiorresearchlabs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Apps

> Learn best practices for testing applications on HyperPaxeer

## Overview

Testing applications on HyperPaxeer follows the same principles as Ethereum development. This guide covers best practices specific to building reliable applications on HyperPaxeer.

> [!NOTE]
>
> For most tests, you don't need Paxeer-specific features. Use your development stack's built-in testing tools for faster iteration.

## Testing Strategy

**1. Unit Tests (Local)**

Test individual functions with framework's local network

**Tools:** Hardhat Network, Anvil (Foundry), Ganache

**Speed:** ⚡ Fastest

**When:** 90% of your tests

**2. Integration Tests (Local Fork)**

Test interactions with deployed contracts

**Tools:** Hardhat forking, Foundry forking

**Speed:** ⚡ Fast

**When:** Testing with existing protocols

**3. Testnet Tests**

Test on live network with real conditions

**Network:** Paxeer Testnet (if available)

**Speed:** 🐌 Slower

**When:** Final validation before mainnet

**4. Mainnet**

Deploy to production

**Network:** HyperPaxeer (Chain ID: 125)

**When:** After thorough testing

## Unit Testing

### Hardhat Example

```javascript test/MyContract.test.js theme={null}
const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("MyContract", function () {
  let contract;
  let owner;
  let addr1;
  let addr2;

  beforeEach(async function () {
    [owner, addr1, addr2] = await ethers.getSigners();
    
    const MyContract = await ethers.getContractFactory("MyContract");
    contract = await MyContract.deploy();
    await contract.waitForDeployment();
  });

  describe("Deployment", function () {
    it("Should set the right owner", async function () {
      expect(await contract.owner()).to.equal(owner.address);
    });

    it("Should start with zero value", async function () {
      expect(await contract.getValue()).to.equal(0);
    });
  });

  describe("Transactions", function () {
    it("Should update value", async function () {
      await contract.setValue(42);
      expect(await contract.getValue()).to.equal(42);
    });

    it("Should emit ValueChanged event", async function () {
      await expect(contract.setValue(42))
        .to.emit(contract, "ValueChanged")
        .withArgs(42);
    });

    it("Should revert when unauthorized", async function () {
      await expect(
        contract.connect(addr1).adminFunction()
      ).to.be.revertedWith("Not authorized");
    });
  });

  describe("Edge Cases", function () {
    it("Should handle zero value", async function () {
      await contract.setValue(0);
      expect(await contract.getValue()).to.equal(0);
    });

    it("Should handle max uint256", async function () {
      const maxUint = ethers.MaxUint256;
      await contract.setValue(maxUint);
      expect(await contract.getValue()).to.equal(maxUint);
    });
  });
});
```

### Foundry Example

```solidity test/MyContract.t.sol theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "../src/MyContract.sol";

contract MyContractTest is Test {
    MyContract public myContract;
    address owner = address(1);
    address user = address(2);

    function setUp() public {
        vm.prank(owner);
        myContract = new MyContract();
    }

    function testSetValue() public {
        myContract.setValue(42);
        assertEq(myContract.getValue(), 42);
    }

    function testEventEmission() public {
        vm.expectEmit(true, true, true, true);
        emit ValueChanged(42);
        myContract.setValue(42);
    }

    function testUnauthorized() public {
        vm.prank(user);
        vm.expectRevert("Not authorized");
        myContract.adminFunction();
    }

    function testFuzz_setValue(uint256 value) public {
        myContract.setValue(value);
        assertEq(myContract.getValue(), value);
    }
}
```

## Integration Testing

### Testing with Mainnet Fork

Fork HyperPaxeer mainnet to test against real deployed contracts:

> [tab] Hardhat
>
> ```javascript hardhat.config.js theme={null}
> module.exports = {
>   networks: {
>     hardhat: {
>       forking: {
>         url: "https://public-rpc.paxeer.app/rpc",
>         blockNumber: 1000000, // Optional: pin to block
>       },
>     },
>   },
> };
> ```
>
> ```javascript test/Integration.test.js theme={null}
> describe("PaxDex Integration", function () {
>   it("Should swap tokens", async function () {
>     const vault = await ethers.getContractAt(
>       "PaxDexVault",
>       "0x49B0f9a0554da1A7243A9C8ac5B45245A66D90ff"
>     );
>
>     // Test with real contract
>     const price = await vault.getPrice(wbtcAddress);
>     expect(price).to.be.gt(0);
>   });
> });
> ```

> [tab] Foundry
>
> ```bash theme={null}
> # Run tests with fork
> forge test --fork-url https://public-rpc.paxeer.app/rpc
> ```
>
> ```solidity test/Integration.t.sol theme={null}
> contract IntegrationTest is Test {
>     function testPaxDexSwap() public {
>         // Fork mainnet
>         vm.createSelectFork("https://public-rpc.paxeer.app/rpc");
>
>         // Interact with real contracts
>         PaxDexVault vault = PaxDexVault(
>             0x49B0f9a0554da1A7243A9C8ac5B45245A66D90ff
>         );
>
>         uint256 price = vault.getPrice(wbtcAddress);
>         assertGt(price, 0);
>     }
> }
> ```

## Gas Testing

### Measure and Optimize Gas Usage

```javascript test/Gas.test.js theme={null}
describe("Gas Optimization", function () {
  it("Should track gas usage", async function () {
    const tx = await contract.setValue(42);
    const receipt = await tx.wait();
    
    console.log("Gas used:", receipt.gasUsed.toString());
    
    // Assert gas usage is within expected range
    expect(receipt.gasUsed).to.be.lt(50000);
  });

  it("Should compare optimized vs unoptimized", async function () {
    // Test optimized function
    const tx1 = await contract.optimizedFunction();
    const receipt1 = await tx1.wait();
    
    // Test unoptimized function
    const tx2 = await contract.unoptimizedFunction();
    const receipt2 = await tx2.wait();
    
    console.log("Optimized gas:", receipt1.gasUsed.toString());
    console.log("Unoptimized gas:", receipt2.gasUsed.toString());
    
    expect(receipt1.gasUsed).to.be.lt(receipt2.gasUsed);
  });
});
```

### Foundry Gas Snapshots

```bash theme={null}
# Create gas snapshot
forge snapshot

# Compare with previous
forge snapshot --diff
```

```solidity theme={null}
contract GasTest is Test {
    function testGas_transfer() public {
        token.transfer(user, 100 ether);
    }
    
    function testGas_batchTransfer() public {
        address[] memory recipients = new address[](10);
        // ... test batch operation
    }
}
```

## Testing Best Practices

> [accordion] Test Coverage
>
> Aim for high test coverage:
>
> ```bash theme={null}
> # Hardhat coverage
> npx hardhat coverage
>
> # Foundry coverage
> forge coverage
> ```
>
> **Target:**
>
> * Statements: > 90%
> * Branches: > 80%
> * Functions: > 90%
> * Lines: > 90%

> [accordion] Test Edge Cases
>
> Test boundary conditions:
>
> ```javascript theme={null}
> describe("Edge Cases", function () {
>   it("Should handle zero", async function () {
>     await contract.setValue(0);
>   });
>
>   it("Should handle max uint256", async function () {
>     await contract.setValue(ethers.MaxUint256);
>   });
>
>   it("Should handle empty arrays", async function () {
>     await contract.processBatch([]);
>   });
>
>   it("Should handle duplicate values", async function () {
>     await contract.addItem(1);
>     await expect(contract.addItem(1)).to.be.reverted;
>   });
> });
> ```

> [accordion] Use Fuzzing
>
> Foundry's fuzzing finds edge cases automatically:
>
> ```solidity theme={null}
> // Foundry will test with random values
> function testFuzz_transfer(uint256 amount) public {
>     vm.assume(amount <= token.balanceOf(address(this)));
>     token.transfer(user, amount);
>     assertEq(token.balanceOf(user), amount);
> }
>
> function testFuzz_division(uint256 a, uint256 b) public {
>     vm.assume(b != 0);
>     uint256 result = a / b;
>     assertLe(result, a);
> }
> ```

> [accordion] Test Events
>
> Verify events are emitted correctly:
>
> ```javascript theme={null}
> it("Should emit Transfer event", async function () {
>   await expect(token.transfer(addr1.address, 100))
>     .to.emit(token, "Transfer")
>     .withArgs(owner.address, addr1.address, 100);
> });
> ```

> [accordion] Time-based Testing
>
> Test time-dependent functionality:
>
> ```javascript theme={null}
> it("Should unlock after time period", async function () {
>   await contract.lock();
>
>   // Fast forward time
>   await ethers.provider.send("evm_increaseTime", [86400]); // 1 day
>   await ethers.provider.send("evm_mine");
>
>   await contract.unlock();
> });
> ```
>
> Foundry:
>
> ```solidity theme={null}
> function testTimeLock() public {
>     contract.lock();
>
>     // Warp time forward
>     vm.warp(block.timestamp + 1 days);
>
>     contract.unlock();
> }
> ```

## Testing Multi-Contract Interactions

```javascript test/MultiContract.test.js theme={null}
describe("Token Vault Integration", function () {
  let token, vault;
  let owner, user;

  beforeEach(async function () {
    [owner, user] = await ethers.getSigners();

    // Deploy token
    const Token = await ethers.getContractFactory("MyToken");
    token = await Token.deploy();

    // Deploy vault
    const Vault = await ethers.getContractFactory("Vault");
    vault = await Vault.deploy(await token.getAddress());

    // Setup: give user some tokens
    await token.transfer(user.address, ethers.parseEther("1000"));
  });

  it("Should deposit and withdraw", async function () {
    const amount = ethers.parseEther("100");

    // User approves vault
    await token.connect(user).approve(await vault.getAddress(), amount);

    // User deposits
    await vault.connect(user).deposit(amount);
    expect(await vault.balances(user.address)).to.equal(amount);
    expect(await token.balanceOf(user.address)).to.equal(
      ethers.parseEther("900")
    );

    // User withdraws
    await vault.connect(user).withdraw(amount);
    expect(await vault.balances(user.address)).to.equal(0);
    expect(await token.balanceOf(user.address)).to.equal(
      ethers.parseEther("1000")
    );
  });
});
```

## Continuous Integration

### GitHub Actions Example

```yaml .github/workflows/test.yml theme={null}
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Install Foundry
        uses: foundry-rs/foundry-toolchain@v1
      
      - name: Run tests
        run: forge test -vvv
      
      - name: Check coverage
        run: forge coverage
```

## Mock Contracts for Testing

```solidity test/mocks/MockERC20.sol theme={null}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

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

contract MockERC20 is ERC20 {
    constructor() ERC20("Mock Token", "MOCK") {
        _mint(msg.sender, 1000000 * 10 ** decimals());
    }
    
    function mint(address to, uint256 amount) external {
        _mint(to, amount);
    }
}
```

## Testing Checklist

Before deploying to HyperPaxeer mainnet:

* [ ] All unit tests passing
* [ ] Integration tests passing
* [ ] Gas costs optimized
* [ ] Test coverage > 90%
* [ ] Edge cases tested
* [ ] Events tested
* [ ] Access control tested
* [ ] Reentrancy protection verified
* [ ] Integer overflow scenarios tested
* [ ] Failed transaction scenarios handled
* [ ] Tested with mainnet fork
* [ ] Security review completed
* [ ] Documentation updated

## Testing Tools & Resources

> [card] [Hardhat](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)
>
> Hardhat testing guide

> [card] [Foundry](https://book.getfoundry.sh/forge/tests)
>
> Foundry testing guide

> [card] [Waffle](https://getwaffle.io)
>
> Ethereum smart contract testing library

> [card] [Chai Matchers](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html)
>
> Ethereum-specific assertions

## Advanced Testing Patterns

### Snapshot Testing

```javascript theme={null}
describe("State Snapshots", function () {
  let snapshotId;

  beforeEach(async function () {
    snapshotId = await ethers.provider.send("evm_snapshot");
  });

  afterEach(async function () {
    await ethers.provider.send("evm_revert", [snapshotId]);
  });

  it("Should test with clean state", async function () {
    // Each test starts with fresh state
    await contract.setValue(42);
    expect(await contract.getValue()).to.equal(42);
  });
});
```

### Testing Reverts

```javascript theme={null}
describe("Revert Scenarios", function () {
  it("Should revert with message", async function () {
    await expect(
      contract.connect(user).adminOnly()
    ).to.be.revertedWith("Only admin");
  });

  it("Should revert with custom error", async function () {
    await expect(
      contract.invalidOperation()
    ).to.be.revertedWithCustomError(contract, "InvalidOperation");
  });

  it("Should revert with panic code", async function () {
    await expect(
      contract.divideByZero()
    ).to.be.revertedWithPanic(0x12); // Division by zero
  });
});
```

### Testing Gas Usage

```javascript theme={null}
describe("Gas Optimization", function () {
  it("Should use less gas than limit", async function () {
    const tx = await contract.optimizedFunction();
    const receipt = await tx.wait();
    
    console.log("Gas used:", receipt.gasUsed.toString());
    expect(receipt.gasUsed).to.be.lt(100000);
  });

  it("Should compare gas between implementations", async function () {
    const tx1 = await contract.methodA();
    const receipt1 = await tx1.wait();
    
    const tx2 = await contract.methodB();
    const receipt2 = await tx2.wait();
    
    console.log("Method A gas:", receipt1.gasUsed.toString());
    console.log("Method B gas:", receipt2.gasUsed.toString());
  });
});
```

## Load Testing

Test your contract under load:

```javascript test/Load.test.js theme={null}
describe("Load Testing", function () {
  it("Should handle batch operations", async function () {
    const numOperations = 100;
    const promises = [];

    for (let i = 0; i < numOperations; i++) {
      promises.push(contract.setValue(i));
    }

    await Promise.all(promises);
    
    // Verify all operations succeeded
    expect(await contract.getValue()).to.equal(numOperations - 1);
  });

  it("Should handle large arrays", async function () {
    const largeArray = Array(1000).fill(0).map((_, i) => i);
    await contract.processBatch(largeArray);
  });
});
```

## Security Testing

> [accordion] Reentrancy Testing
>
> ```solidity test/Reentrancy.t.sol theme={null}
> contract ReentrancyTest is Test {
>     Vulnerable vulnerable;
>     Attacker attacker;
>
>     function setUp() public {
>         vulnerable = new Vulnerable();
>         attacker = new Attacker(address(vulnerable));
>     }
>
>     function testReentrancyAttack() public {
>         vm.deal(address(vulnerable), 10 ether);
>         vm.deal(address(attacker), 1 ether);
>
>         vm.expectRevert("ReentrancyGuard: reentrant call");
>         attacker.attack();
>     }
> }
> ```

> [accordion] Access Control Testing
>
> ```javascript theme={null}
> describe("Access Control", function () {
>   it("Owner can perform admin actions", async function () {
>     await expect(contract.connect(owner).adminAction())
>       .to.not.be.reverted;
>   });
>
>   it("Non-owner cannot perform admin actions", async function () {
>     await expect(contract.connect(user).adminAction())
>       .to.be.revertedWith("Ownable: caller is not the owner");
>   });
>
>   it("Should transfer ownership", async function () {
>     await contract.transferOwnership(user.address);
>     expect(await contract.owner()).to.equal(user.address);
>   });
> });
> ```

> [accordion] Integer Overflow Testing
>
> ```solidity theme={null}
> function testOverflow() public {
>     uint256 max = type(uint256).max;
>
>     // Should revert in 0.8+
>     vm.expectRevert();
>     uint256 overflow = max + 1;
> }
> ```

## CI/CD Integration

### Automated Testing Pipeline

```yaml .github/workflows/ci.yml theme={null}
name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
        with:
          submodules: recursive
      
      - name: Install Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run tests
        run: npx hardhat test
      
      - name: Check coverage
        run: npx hardhat coverage
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
```

## Debugging Tests

### Enable Verbose Logging

```bash theme={null}
# Hardhat
npx hardhat test --verbose

# Foundry
forge test -vvvv
```

### Use Console.log in Solidity

```solidity theme={null}
import "hardhat/console.sol";

contract Debug {
    function testFunction(uint256 x) external {
        console.log("Input value:", x);
        uint256 result = x * 2;
        console.log("Result:", result);
    }
}
```

### Hardhat Debugging

```javascript theme={null}
const { ethers } = require("hardhat");

it("Should debug transaction", async function () {
  const tx = await contract.setValue(42);
  const receipt = await tx.wait();
  
  console.log("Transaction hash:", receipt.hash);
  console.log("Block number:", receipt.blockNumber);
  console.log("Gas used:", receipt.gasUsed.toString());
  console.log("Logs:", receipt.logs);
});
```

## Resources

> [card] [Building Apps](https://sidiorresearchlabs.mintlify.site/app-developers/guides/building-apps.md)
>
> Development guide

> [card] [Examples](https://sidiorresearchlabs.mintlify.site/examples.md)
>
> Code examples

> [card] [Hardhat Testing](https://hardhat.org/hardhat-runner/docs/guides/test-contracts)
>
> Hardhat test guide

> [card] [Foundry Testing](https://book.getfoundry.sh/forge/tests)
>
> Foundry test guide

## Next Steps

> [card] [Deploy Contracts](https://sidiorresearchlabs.mintlify.site/contracts.md)
>
> Deploy to HyperPaxeer

> [card] [Transaction Guides](https://sidiorresearchlabs.mintlify.site/app-developers/guides/transactions/fees.md)
>
> Understand transactions

> [card] [Security](https://sidiorresearchlabs.mintlify.site/concepts/security/best-practices)
>
> Security best practices


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.