Running Tests
The project uses Forge for comprehensive smart contract testing.Basic Test Execution
Run all tests in the project:- Compiles all contracts
- Executes all test files in the
test/directory - Generates gas benchmarks (saved to
snapshots/folder) - Reports test results with gas usage
Verbose Output
For detailed test execution information:Excluding E2E Tests
Some tests require internet connectivity to interact with live networks. To run tests without these end-to-end tests:- CI/CD pipelines without network access
- Faster local development iterations
- Running tests without external dependencies
E2E tests validate integration with real flash loan providers like Aave and Maker, so they should be run before production deployments.
Test Organization
Tests are typically organized in the following structure:Running Specific Tests
By Test File
By Test Contract
By Test Function
Combined Filters
Gas Benchmarking
The repository includes automated gas benchmarking for different flash loan providers.Generate Benchmarks
Gas snapshots are automatically generated when running tests:snapshots/ directory:
View Gas Report
Generate a detailed gas usage report:Update Snapshots
To update gas snapshots after contract changes:Test Configuration
Test settings are configured infoundry.toml:
Transaction Isolation
Theisolate = true setting ensures:
- Each function call in a test is an independent transaction
- Transient storage is cleared between calls
- More accurate simulation of real-world behavior
Writing Tests
Test Structure
Foundry tests use Solidity and follow this pattern:Common Test Patterns
Testing with different users
Testing with different users
Testing events
Testing events
Fuzzing tests
Fuzzing tests
Testing with mocks
Testing with mocks
Continuous Integration
For CI environments, use the CI profile with strict settings:foundry.toml):
Test Coverage
Generate test coverage reports:Debugging Tests
Debug Mode
Run a specific test in debug mode:- Step through transactions
- Inspect state variables
- View stack traces
- Examine memory and storage
Console Logging
Add debug output to your tests:-vv to see console output:
Common Testing Scenarios
Unit Tests
Test individual contract functions in isolation:
- FlashLoanRouter authentication
- Borrower flash loan triggers
- Approval management
- Access control
Integration Tests
Test contract interactions:
- Router + Borrower coordination
- Multiple flash loans in sequence
- Settlement execution flow
- Token transfers
E2E Tests
Test with real protocols:
- Aave flash loans
- Maker flash mints
- CoW Protocol settlements
- Multi-network deployments
Security Tests
Test security properties:
- Reentrancy protection
- Access control validation
- Flash loan repayment
- Invariant testing
Best Practices
- Test organization: Group related tests in descriptive contracts
- Clear test names: Use descriptive names like
testFlashLoanRevertsWithInsufficientApproval - Setup isolation: Each test should be independent and reproducible
- Edge cases: Test boundary conditions, zero values, and maximum amounts
- Error cases: Test expected failures with
vm.expectRevert() - Gas optimization: Monitor gas usage with benchmarks
- Documentation: Comment complex test scenarios
Troubleshooting
Test fails in CI but passes locally
Test fails in CI but passes locally
Common causes:
- Different Forge versions
- Network-dependent tests not excluded
- Non-deterministic behavior (use fixed seeds)
- Missing environment variables
FOUNDRY_PROFILE=ci locally to reproduce CI environment.Out of gas errors
Out of gas errors
Increase the gas limit for tests:Or in
foundry.toml:Transient storage issues
Transient storage issues
The
isolate = true setting handles transient storage. If you encounter issues:- Verify
isolate = trueinfoundry.toml - Update to latest Forge version
- Check Foundry issue #6908