Common Libraries & Tooling

These libraries are used across the stack to write tests, simulate transactions, connect wallets, and interface with the blockchain in both scripting and frontend contexts.

LibraryPurposeKey Features
Ethers.jsContract interaction, transaction signing, provider management in JS/TS environmentsProvides Contract, Provider, Wallet, and Interface abstractions. Deep Hardhat integration. ABI coder, calldata utilities, and ENS support.
ViemModular TypeScript-first library for RPC, contract access, encoding, and data formattingTree-shakeable. Supports batching, client-side caching, EIP-1559 fees, multicalls, typed reads/writes. Used by Wagmi.
WagmiReact hooks for wallet connection, chain state, and contract calls in frontend appsBuilt on Viem. Includes useAccount, useConnect, useContractRead, and event subscriptions. Enables seamless integration with wallet modals.
Web3.jsLegacy Ethereum contract and RPC libraryOne of the earliest libraries. Now largely unmaintained. Lacks EIP-1559 support and modern modularity.
RainbowKitReact component library for wallet connection UI and chain managementPre-built wallet connect buttons, chain switch UI, and custom themes. Integrates with Wagmi for wallet state management and tx handling.

Ethers and Viem serve similar purposes, but Viem is optimized for frontend apps. Wagmi builds on Viem. Web3.js is no longer recommended for new projects.


Testing Frameworks

Note Smart contract quality and security depend on a comprehensive testing strategy including but not limited to:

  • Unit Tests: Verify individual functions and components
  • Property-Based Fuzzing: Test invariants with random inputs
  • Code Coverage: Ensure all code paths are tested
  • Static Analysis: Detect common vulnerabilities and anti-patterns

The tools and frameworks below provide a foundation for each of these testing layers.

Foundry — Solidity-Native

  • Tests written directly in Solidity.
  • Very fast runner (forge test) and rich cheatcodes for state manipulation.
  • Built-in, configurable fuzzing (forge test --fuzz-runs=N).
  • Includes tools like forge script, forge coverage, and forge snapshot.

Hardhat — JavaScript / TypeScript

  • Mocha + Chai test runner for JS/TS-based tests.
  • Flexible task system (hardhat.config.js), plugin support, and network forking.
  • Integrates with Ethers.js and Solidity tooling for deployments, gas tracking, and test orchestration.

Fuzz (Property-Based) Testing

Fuzz testing generates random inputs to find edge cases that violate expected properties.

test/MyContract.t.sol (Foundry)
// test/MyContract.t.sol  (Foundry)
function test_myFunction_fuzz(uint256 amount) public {
    vm.assume(amount > 0 && amount < 1e18);   // constrain input
    myContract.myFunction(amount);
    assertEq(myContract.someState(), expectedValue);
}
ToolNotes
FoundryBuilt-in fuzzing; enabled by default when running forge test.
EchidnaExternal, property-based fuzzer. Supports invariants and campaigns.

Use fuzzing to test against invariants such as:

  • balance never exceeds total supply
  • no overflow or underflow under bounded inputs
  • access control is consistently enforced

Supplementary Tools

Tools that enhance test coverage, assert correctness, or catch common vulnerabilities.

ToolPurposeTypical Command
OpenZeppelin Test HelpersTime travel, event assertions, revertsJS/TS only. Works with Hardhat + Mocha.
solidity-coverageReports untested branches in Soliditynpx hardhat coverage · forge coverage
SlitherStatic analysis for known vuln patternsslither .

Example — OpenZeppelin Test Helpers

const { time, expectRevert } = require('@openzeppelin/test-helpers');

// advance clock by one day
await time.increase(time.duration.days(1));

// expect revert with specific reason
await expectRevert(contract.someFunction(), "Ownable: caller is not the owner");