Overview
Fishnet includes a comprehensive test suite with 100+ tests covering:- Core functionality: Permit validation, execution, access control
- EIP-712 compatibility: Rust ↔ Solidity encoding compatibility
- Edge cases: Expiry boundaries, nonce ordering, reentrancy protection
- Attack surface: Fuzzing, malicious inputs, signature malleability
- End-to-end flows: Full integration tests with FFI to Rust signer
Quick Start
Run all tests:Test Suites
1. Core Functionality Tests
File:test/FishnetWallet.t.sol (766 lines)
Coverage: Constructor, execute(), setSigner(), withdraw(), pause(), unpause()
Run core tests:
test_executeValidPermit
test_executeValidPermit
Verifies a valid permit executes successfully, transfers ETH, marks nonce as used, and emits
ActionExecuted event.test/FishnetWallet.t.sol:153-177
test_execute_reverts_permitExpired
test_execute_reverts_permitExpired
Verifies expired permits are rejected.
test/FishnetWallet.t.sol:197-209
test_execute_reverts_nonceAlreadyUsed
test_execute_reverts_nonceAlreadyUsed
Verifies nonce replay protection.
test/FishnetWallet.t.sol:232-246
test_reentryProtection
test_reentryProtection
Verifies reentrancy attacks are prevented.
test/FishnetWallet.t.sol:632-661
2. EIP-712 Compatibility Tests
File:test/EIP712Compatibility.t.sol (303 lines)
Coverage: Rust-Solidity encoding compatibility, domain separator, struct hash, signatures
Run compatibility tests:
test_permitTypehashMatchesSolidity
test_permitTypehashMatchesSolidity
Verifies the Rust typehash matches Solidity’s
PERMIT_TYPEHASH.test/EIP712Compatibility.t.sol:36-51
test_domainSeparatorEncoding
test_domainSeparatorEncoding
Verifies Rust’s manual domain separator construction matches Solidity’s
DOMAIN_SEPARATOR().test/EIP712Compatibility.t.sol:57-86
test_structHashEncoding
test_structHashEncoding
Verifies Rust’s manual struct hash encoding matches Solidity’s
abi.encode().This test is critical because it verifies that uint64 and uint48 padding is identical between Rust and Solidity.test/EIP712Compatibility.t.sol:92-140
test_rustSignerEndToEnd
test_rustSignerEndToEnd
Full end-to-end test: compute digest → sign → execute.This mirrors the exact code path in
crates/server/src/signer.rs:eip712_hash().test/EIP712Compatibility.t.sol:146-182
test_abiEncodePaddingMatchesRust
test_abiEncodePaddingMatchesRust
Verifies
abi.encode(uint64) and abi.encode(uint48) produce left-padded 32-byte values identical to Rust’s manual padding.test/EIP712Compatibility.t.sol:264-290
3. Fuzz Tests
File:test/FishnetWalletFuzz.t.sol (10,691 bytes)
Coverage: Random inputs, boundary values, gas usage
Run fuzz tests:
4. Attack Surface Tests
File:test/AttackSurface.t.sol (18,072 bytes)
Coverage: Malicious inputs, signature forgery, front-running
Run attack surface tests:
5. End-to-End Integration Tests
File:test/FishnetWalletE2E.t.sol (14,888 bytes)
Coverage: Full deployment → fund → sign → execute flows
Run E2E tests:
6. Rust Signer FFI Tests
File:test/RustSignerFFI.t.sol (9,384 bytes)
Coverage: FFI calls to Rust signer, cross-language compatibility
These tests use Foundry’s FFI to call the actual Rust signer implementation.
Run FFI tests:
Test Coverage
Generate coverage report:coverage/index.html in your browser.
Expected Coverage: ~95%+ statement coverage, ~90%+ branch coverage
Gas Benchmarks
Run gas benchmarks:Running Specific Test Categories
Integration Test Script
Run the full Anvil-based integration test:- Starts a local Anvil node
- Deploys FishnetWallet
- Signs a permit using
cast - Executes the permit on-chain
- Verifies the transaction succeeded
Debugging Failed Tests
Verbose Logging
Use-vvv for stack traces:
-vvvv for full EVM traces:
Isolate Failing Tests
Run only tests matching a pattern:Enable Console Logs
Add console logs to tests:-vv to see logs:
Continuous Integration
Add to your CI pipeline:.github/workflows/test.yml
Test Utilities
Helper Functions
The test suite includes reusable helpers:test/FishnetWallet.t.sol:77-121
Mock Contracts
The test suite includes mock targets:test/FishnetWallet.t.sol:7-46
Expected Test Results
All tests should pass:Troubleshooting
Error: FFI is disabled
Error: FFI is disabled
FFI tests require
ffi = true in foundry.toml. This is already enabled in the Fishnet config.If you see this error, check foundry.toml:5:Error: Signature verification failed
Error: Signature verification failed
This usually indicates an EIP-712 encoding mismatch. Run the compatibility tests:Check the domain separator and struct hash computations.
Gas limit exceeded
Gas limit exceeded
Some complex tests may hit gas limits. Increase the gas limit in
foundry.toml or use vm.txGasPrice().Test takes too long
Test takes too long
Reduce fuzz runs:
foundry.toml
Next Steps
Deploy Contracts
Deploy FishnetWallet to testnets or mainnet
EIP-712 Permits
Learn how permits are structured and signed