Testing Assertions
How to test assertions
Testing assertions is very similar to writing regular Forge tests. If you’re familiar with Forge testing, you’ll feel right at home. You get access to all the same testing utilities:
- Standard assertions (
assertEq
,assertTrue
, etc.) - Cheatcodes (
vm.prank
,vm.deal
,vm.warp
, etc.) - Console logging
- Test setup with
setUp()
function
Credible Layer Testing Interface
The Credible Layer extends Forge’s testing capabilities with additional utilities specifically for testing assertions. Here’s the key interface:
Using the Testing Interface
Here’s how to use these utilities in your tests:
Key concepts:
- Use
cl.addAssertion()
to register assertions with contracts you want to monitor - Use
cl.validate()
to test how assertions respond to transactions - No return value from
cl.validate()
, but you can usevm.expectRevert()
to check if it reverts - Multiple assertions can be linked to the same contract
- Use the
label
to specify the assertion contract name for easier debugging
This means you can leverage your existing Forge testing knowledge while using these additional features to verify your assertions work correctly.
Testing Patterns
This section shows useful patterns that can be used when testing assertions.
Batch Operation Testing Pattern
This pattern is used to test assertions that need to verify behavior across multiple operations in a single transaction. It involves creating a helper contract that performs multiple operations in its fallback function, allowing us to test the assertion’s ability to track and validate the cumulative effect of these operations.
Key Components:
- A helper contract with a fallback function that performs multiple operations
- Testing by calling the helper contract’s fallback with empty calldata
- Verification of the final state after all operations
Example Implementation:
Benefits:
- Tests multiple operations in a single transaction
- Verifies that assertions can track cumulative effects
- More realistic testing of real-world scenarios
This pattern is used in assertions like the Sum of all positions to test how multiple operations affect intra-transaction state changes. It’s particularly valuable for assertions that need to verify invariants across complex sequences of operations within a single transaction.
Protocol Mocking
When testing assertions, it can be difficult to trigger the conditions that would cause an assertion to fail in a real protocol. This is because protocols are designed to be secure and prevent invalid states from occurring. Protocol mocking provides a solution by creating simplified versions of protocols that can be intentionally put into invalid states. For example, you might create a mock protocol that allows direct manipulation of balances or total supply to test if your assertion correctly catches these invalid states.
Key Components:
- Create a mock protocol with simplified logic
- Test by intentionally putting the protocol into an invalid state
- Verify that the assertion correctly catches the invalid state
You can see examples of mock protocols in the Assertion Examples repository.