Home

Awesome

Using Halmos to Formally Verify Solady's FixedPointMathLib

Halmos is a symbolic bounded model checker. It takes in EVM bytecode, converts it to a series of equations, and uses Z3 Theorem Prover to verify the assertion or find counterexamples.

Z3 struggles with certain types of equations, so we can't just formally verify everything. Depending on the situation, either:

This repo is a work in progress, focused on verifying the functions with to the highest degree possible.

Repo Organization

Because of the limitations of deployed contract size in Halmos tests, all functions are broken apart into separate contracts in src/.

Each function has a separate test in test/. Some tests are written for Foundry fuzzing, while others are written for Halmos. Instructions are provided at the top of each test file explaining how best to run each test.

FixedPointMathLib Functions

Detailed Breakdown

✅ sqrt()

To run:

Explanation: All differences between the two implementations exist in the first half of the function, so we abstract out the final (identical) piece, to leave just the differences. We can then test solmateSqrt and soladySqrt with a fuzz test to ensure the changes didn't break anything. Once this is provide, we can remove the call to the identical internal function, leaving solmateSqrtStripped and soladySqrtStripped, which we can test for equivalence with Halmos.

✅ mulWad()

To run:

Explanation: This one is relatively simple with minimal division, so Halmos can handle the functions as-is. We simply compare them both to a non-assembly non-optimized version, and prove equivalence.

✅ mulWadUp()

To run:

Explanation: Halmos isn't able to prove the correctness, because the math to get the correct value in pure Solidity is too complex. So we prove the correctness with a fuzz test and then prove the equivalence of the two full functions with Halmos.

✅ log2()

To run:

Explanation: The Solady code is verified to be correct by definition. The definition of log2 is the most significant bit that is set to 1. This test proves the equivalence between the Solady code and (much less efficient but simple code) that loops over the bits and returns the index of the most significant one. Note that that log2(0) is undefined, but the code returns 0 for that case. Because the reference code uses a for loop, we need to explicitly tell Halmos to unwrap the loop 256 times to ensure the code paths are fully explored.