Documentation Index Fetch the complete documentation index at: https://mintlify.com/reserve-protocol/reserve-index-dtf/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Reserve Folio uses Foundry as its primary testing framework. The test suite includes unit tests, integration tests, and extreme condition tests to ensure protocol security and correctness.
Running Tests
Basic Test Suite
Run all tests except extreme tests:
This executes forge test --no-match-test extreme and runs the standard test suite.
Extreme Tests
Extreme tests verify the protocol behavior under edge cases and boundary conditions:
This runs tests with the extreme keyword in their name, testing scenarios like:
Maximum token supplies (1e36)
Extreme price ranges
Boundary basket weights
Large-scale rebalancing operations
All Tests
Run the complete test suite including extreme tests:
Running all tests may take several minutes and requires significant computational resources due to the extreme test cases.
Specific Test Files
Run tests from a specific file:
forge test --match-path test/Folio.t.sol
Specific Test Functions
Run a specific test function:
forge test --match-test testMintAndRedeem
Verbose Output
Get detailed output including console logs:
Verbosity levels:
-v: Show test results
-vv: Show test results and logs for failed tests
-vvv: Show test results and logs for all tests
-vvvv: Show test results, logs, and traces
-vvvvv: Show test results, logs, traces, and setup traces
Test Coverage
Generate Coverage Report
Generate an LCOV coverage report:
This creates a lcov.info file that can be viewed with coverage tools.
Coverage Summary
View a quick coverage summary in the terminal:
Example output:
| File | % Lines | % Statements | % Branches | % Funcs |
|-------------------------------|---------------|---------------|---------------|---------------|
| contracts/Folio.sol | 98.50% | 98.75% | 95.00% | 100.00% |
| contracts/StakingVault.sol | 97.25% | 97.50% | 93.75% | 100.00% |
| Total | 97.80% | 98.00% | 94.25% | 99.50% |
Test Structure
Directory Organization
The test suite is organized as follows:
test/
├── base/
│ ├── BaseTest.sol # Base test contract with common setup
│ └── BaseExtremeTest.sol # Base for extreme condition tests
├── utils/
│ ├── MockERC20.sol # Mock ERC20 token for testing
│ ├── MockBidder.sol # Mock auction bidder
│ ├── MockRoleRegistry.sol # Mock role registry
│ └── upgrades/
│ ├── FolioV2.sol # Mock upgrade version
│ └── FolioDeployerV2.sol # Mock deployer upgrade
├── Folio.t.sol # Core Folio contract tests
├── FolioDeployer.t.sol # Deployer tests
├── FolioDAOFeeRegistry.t.sol # Fee registry tests
├── FolioVersionRegistry.t.sol # Version registry tests
├── StakingVault.t.sol # Staking vault tests
├── Governance.t.sol # Governance tests
├── GovernanceDeployer.t.sol # Governance deployer tests
├── Allowlist.t.sol # Allowlist functionality tests
└── Extreme.t.sol # Extreme condition tests
Base Test Contract
All tests inherit from BaseTest.sol, which provides:
abstract contract BaseTest is Script , Test {
// Common test addresses
address auctionLauncher = 0x00000000000000000000000000000000000000cc ;
address dao = 0xDA00000000000000000000000000000000000000 ;
address owner = 0xCc00000000000000000000000000000000000000 ;
address user1 = 0xfF00000000000000000000000000000000000000 ;
address user2 = 0xbb00000000000000000000000000000000000000 ;
// Test tokens
IERC20 USDC;
IERC20 DAI;
IERC20 MEME;
// Core contracts
Folio folio;
FolioDeployer folioDeployer;
FolioDAOFeeRegistry daoFeeRegistry;
function setUp () public virtual {
// Setup logic
}
}
Writing Tests
Test Function Naming
Follow these conventions:
function test_DescriptiveTestName () public {
// Test succeeds if it doesn't revert
}
function testFail_ExpectedFailure () public {
// Test succeeds if it reverts
}
function test_RevertWhen_Condition () public {
// Test expects a revert with specific condition
vm. expectRevert (ErrorSelector);
// Action that should revert
}
function test_extreme_BoundaryCondition () public {
// Extreme test case
}
Example Test
function test_MintAndRedeem () public {
// Arrange
uint256 mintAmount = 1000e18 ;
deal ( address (USDC), user1, mintAmount);
vm. startPrank (user1);
USDC. approve ( address (folio), mintAmount);
// Act
uint256 sharesBefore = folio. balanceOf (user1);
folio. mint (mintAmount, user1);
uint256 sharesAfter = folio. balanceOf (user1);
// Assert
assertGt (sharesAfter, sharesBefore);
assertEq (USDC. balanceOf ( address (folio)), mintAmount);
// Act - Redeem
uint256 sharesReceived = sharesAfter - sharesBefore;
folio. redeem (sharesReceived, user1, user1);
// Assert
assertEq (folio. balanceOf (user1), sharesBefore);
vm. stopPrank ();
}
Testing Reverts
function test_RevertWhen_UnauthorizedAccess () public {
vm. prank (user1);
vm. expectRevert (
abi . encodeWithSelector (
IAccessControl.AccessControlUnauthorizedAccount.selector,
user1,
folio. REBALANCE_MANAGER ()
)
);
folio. startRebalance ( /* params */ );
}
Using Cheatcodes
Foundry provides powerful testing cheatcodes:
// Manipulate time
vm. warp ( block .timestamp + 1 days );
// Set msg.sender
vm. prank (user1);
folio. deposit (amount);
// Set msg.sender for multiple calls
vm. startPrank (user1);
token. approve ( address (folio), amount);
folio. deposit (amount);
vm. stopPrank ();
// Give tokens to address
deal ( address (token), user1, 1000e18 );
// Mock external calls
vm. mockCall (
address (oracle),
abi . encodeWithSelector (IOracle.getPrice.selector),
abi . encode ( 1e27 )
);
// Expect events
vm. expectEmit ( true , true , true , true );
emit Deposit (user1, amount, shares);
Testing Best Practices
Arrange-Act-Assert Pattern
Structure tests with clear sections:
Arrange : Set up test conditions
Act : Execute the function being tested
Assert : Verify the expected outcomes
Each test should verify a single behavior or requirement. This makes tests easier to understand and debug.
Test names should clearly describe what is being tested and under what conditions. Good: test_RevertWhen_MintingAboveSupplyCap
Bad: test_Mint2
Always test boundary conditions:
Zero values
Maximum values
Empty arrays
Invalid inputs
Each test should be independent and not rely on state from other tests.
Gas Reporting
Generate gas usage reports:
Optionally filter by contract:
forge test --gas-report --match-contract Folio
Debugging Failed Tests
Interactive Debugging
Use Forge’s debugger:
forge test --match-test testName --debug
Trace Execution
Show detailed execution traces:
forge test --match-test testName -vvvvv
Isolate Failures
Run only failed tests:
Continuous Integration
Tests run automatically on:
Every pull request
Commits to main branch
Before deployments
Ensure all tests pass before submitting a pull request:
yarn test:all && yarn coverage:summary
Next Steps
Deployment Deploy contracts to testnets and mainnet
Contributing Learn how to contribute to the protocol