Testing Frameworks
Comprehensive Testing Approach
Testing is essential for validating smart contract security and correctness. We employ a variety of testing frameworks and methodologies to provide comprehensive coverage and find vulnerabilities that might be missed by static analysis.
Core Testing Frameworks
Hardhat
Description: Hardhat is a development environment for Ethereum software, designed for professional developers. It features built-in testing and debugging capabilities.
Use Cases:
- Unit and integration testing
- Local blockchain simulation
- Contract deployment testing
- Gas usage optimization
Key Features:
- JavaScript/TypeScript testing environment
- Console.log debugging
- Stack traces for errors
- Network forking capabilities
- Plugin ecosystem
Integration in Our Process: We use Hardhat for comprehensive test suites, particularly for complex DeFi protocols where interaction with mainnet contracts is required.
Foundry (Forge/Cast)
Description: Foundry is a blazing fast, portable and modular toolkit for Ethereum application development, with a focus on testing efficiency.
Use Cases:
- High-performance smart contract testing
- Fuzzing and property-based testing
- Gas optimization
- Mainnet forking and simulation
Key Features:
- Written in Rust for high performance
- Solidity-native testing
- Advanced fuzzing capabilities
- Cheatcodes for state manipulation
- Extensive trace outputs
Integration in Our Process: We leverage Foundry for its performance advantages and powerful fuzzing capabilities, particularly for projects requiring extensive test permutations.
Specialized Testing Tools
Echidna
Description: Echidna is a property-based fuzzing tool designed specifically for Ethereum smart contracts.
Use Cases:
- Finding edge cases through fuzzing
- Property-based testing
- Invariant testing
- Discovering unexpected state transitions
Key Features:
- Smart fuzzing based on coverage
- Property testing in Solidity
- Corpus generation and mutation
- Detailed test case reporting
Integration in Our Process: We apply Echidna to discover edge cases and boundary conditions that might not be covered by standard test suites.
Tenderly
Description: Tenderly is a platform for monitoring, alerting, debugging, and simulating Ethereum smart contracts.
Use Cases:
- Transaction simulation and debugging
- Gas profiling
- Contract verification
- Real-time monitoring
Key Features:
- Visual debugger
- Gas profiler
- Custom alerts and notifications
- Transaction simulations
Integration in Our Process: We use Tenderly for simulating complex interactions and debugging transaction failures during the verification phase.
Testing Methodologies
Unit Testing
Our unit testing approach:
- Tests each function in isolation
- Verifies correct behavior for valid inputs
- Checks proper handling of invalid inputs
- Confirms expected events are emitted
- Verifies state changes
Integration Testing
Our integration testing strategy:
- Tests interactions between contract components
- Verifies correct composite behavior
- Checks multi-step workflows
- Tests contract upgrades and migrations
Property-Based Testing
We employ property-based testing to:
- Identify invariants that should always hold
- Generate random inputs to test boundary conditions
- Discover unexpected edge cases
- Verify mathematical properties
Economic Testing
For DeFi protocols, we conduct economic testing to:
- Simulate various market conditions
- Test economic incentive alignment
- Verify no adversarial profit opportunities exist
- Check resistance to common economic attacks
Scenario Testing
We develop scenario tests to:
- Simulate real-world usage patterns
- Test complex interaction sequences
- Verify behavior in extreme conditions
- Check recovery from failure states
Testing Best Practices
Our testing process follows these best practices:
Coverage-Driven Testing
- We aim for 100% code coverage where practical
- Beyond line coverage, we focus on path and branch coverage
- We identify and test critical paths extensively
- Coverage reports guide additional test development
Gas Optimization Testing
- We measure gas consumption in tests
- We compare gas usage against baselines
- We identify gas-intensive operations and optimization opportunities
- We test gas usage under different network conditions
Mainnet Forking
- We test against production state when relevant
- We simulate interactions with existing protocols
- We verify compatibility with deployed contracts
- We check behavior with real-world data and state
Continuous Integration
- We integrate testing into CI/CD pipelines
- We enforce test passage before deployment
- We track test metrics over time
- We maintain regression test suites
Comprehensive testing is not merely a verification step but an integral part of the security development lifecycle. By combining multiple testing frameworks and methodologies, we can identify and address vulnerabilities that might otherwise reach production.