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

<Info>
  For most tests, you don't need Paxeer-specific features. Use your development stack's built-in testing tools for faster iteration.
</Info>

## Testing Strategy

<Steps>
  <Step title="Unit Tests (Local)">
    Test individual functions with framework's local network

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

    **Speed:** ⚡ Fastest

    **When:** 90% of your tests
  </Step>

  <Step title="Integration Tests (Local Fork)">
    Test interactions with deployed contracts

    **Tools:** Hardhat forking, Foundry forking

    **Speed:** ⚡ Fast

    **When:** Testing with existing protocols
  </Step>

  <Step title="Testnet Tests">
    Test on live network with real conditions

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

    **Speed:** 🐌 Slower

    **When:** Final validation before mainnet
  </Step>

  <Step title="Mainnet">
    Deploy to production

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

    **When:** After thorough testing
  </Step>
</Steps>

## 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:

<Tabs>
  <Tab title="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>

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

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

<AccordionGroup>
  <Accordion title="Test Coverage" icon="shield-check">
    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>

  <Accordion title="Test Edge Cases" icon="triangle-exclamation">
    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>

  <Accordion title="Use Fuzzing" icon="shuffle">
    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>

  <Accordion title="Test Events" icon="bell">
    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>

  <Accordion title="Time-based Testing" icon="clock">
    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();
    }
    ```
  </Accordion>
</AccordionGroup>

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

<CardGroup cols={2}>
  <Card title="Hardhat" icon="hammer" href="https://hardhat.org/hardhat-runner/docs/guides/test-contracts">
    Hardhat testing guide
  </Card>

  <Card title="Foundry" icon="anvil" href="https://book.getfoundry.sh/forge/tests">
    Foundry testing guide
  </Card>

  <Card title="Waffle" icon="mug-hot" href="https://getwaffle.io">
    Ethereum smart contract testing library
  </Card>

  <Card title="Chai Matchers" icon="check" href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html">
    Ethereum-specific assertions
  </Card>
</CardGroup>

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

<AccordionGroup>
  <Accordion title="Reentrancy Testing" icon="shield">
    ```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>

  <Accordion title="Access Control Testing" icon="lock">
    ```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>

  <Accordion title="Integer Overflow Testing" icon="calculator">
    ```solidity theme={null}
    function testOverflow() public {
        uint256 max = type(uint256).max;
        
        // Should revert in 0.8+
        vm.expectRevert();
        uint256 overflow = max + 1;
    }
    ```
  </Accordion>
</AccordionGroup>

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

<CardGroup cols={2}>
  <Card title="Building Apps" icon="hammer" href="/app-developers/guides/building-apps">
    Development guide
  </Card>

  <Card title="Examples" icon="code" href="/examples">
    Code examples
  </Card>

  <Card title="Hardhat Testing" icon="book" href="https://hardhat.org/hardhat-runner/docs/guides/test-contracts">
    Hardhat test guide
  </Card>

  <Card title="Foundry Testing" icon="book" href="https://book.getfoundry.sh/forge/tests">
    Foundry test guide
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Deploy Contracts" icon="upload" href="/contracts">
    Deploy to HyperPaxeer
  </Card>

  <Card title="Transaction Guides" icon="money-bill" href="/app-developers/guides/transactions/fees">
    Understand transactions
  </Card>

  <Card title="Security" icon="shield" href="/concepts/security/best-practices">
    Security best practices
  </Card>
</CardGroup>
