Differential Testing Explained in Detail
Differential testing feeds the same inputs or action sequences to two systems and compares the results. The systems might be an old version and a new version, a simple reference and an optimized implementation, or two chain deployments.
It is especially useful when code is refactored, optimized, or upgraded.
Smart contract example
assertEq(newVault.previewDeposit(x), oldVault.previewDeposit(x));
If the outputs differ, the test should explain whether the difference is expected.
Differential Testing in Auditing
Many bugs appear when teams rewrite math, upgrade vaults, or port protocols across chains. Differential testing catches unintended behavior changes quickly.
Auditors use it to protect accounting, pricing, and permission behavior during changes.
Red flags in code
-
The reference implementation is assumed correct without review.
-
Rounding differences are ignored or overaccepted.
-
Tests compare only outputs, not state changes.
-
Stateful action sequences are missing.
-
Edge inputs are not fuzzed.
How to test or review it
-
Define which differences are allowed.
-
Compare outputs, events, balances, and storage changes.
-
Use fuzzing for input ranges and action sequences.
-
Include edge cases around zero, max values, and rounding boundaries.
-
Pair with invariant testing for stateful protocols.