Testing applications on HyperPaxeer follows the same principles as Ethereum development. This guide covers best practices specific to building reliable applications on HyperPaxeer.
For most tests, you don’t need Paxeer-specific features. Use your development stack’s built-in testing tools for faster iteration.
// SPDX-License-Identifier: MITpragma 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); }}
# Create gas snapshotforge snapshot# Compare with previousforge snapshot --diff
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 }}
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; });});
Use Fuzzing
Foundry’s fuzzing finds edge cases automatically:
// Foundry will test with random valuesfunction 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);}
Test Events
Verify events are emitted correctly:
it("Should emit Transfer event", async function () { await expect(token.transfer(addr1.address, 100)) .to.emit(token, "Transfer") .withArgs(owner.address, addr1.address, 100);});
Time-based Testing
Test time-dependent functionality:
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:
function testTimeLock() public { contract.lock(); // Warp time forward vm.warp(block.timestamp + 1 days); contract.unlock();}
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); });});
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(); }}
Access Control Testing
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); });});
Integer Overflow Testing
function testOverflow() public { uint256 max = type(uint256).max; // Should revert in 0.8+ vm.expectRevert(); uint256 overflow = max + 1;}