Preliminary Repository's https://cantina.xyz/code/8b94fd62-eea5-46fb-bed6-36ec5adf36af/README.mdhttps://github.com/cantina-forks/thala-modules/tree/mai
Formal verification of key modules within the Aave V3 codebase was conducted using an aggressive threat modeling approach with the prover. The process rigorously tested abort conditions, state consistency, authorization checks, and asset conservation to ensure secure and correct operation under all scenarios. This verification focused on mitigating potential threats and maintaining protocol integrity, ensuring the reliability of staking and reward mechanisms.
Modules include:
aave_math::wad_ray_math.move| Functionality | Details | Verification Status |
|---|---|---|
function wade_to_ray |
||
| Preconditions | Input a must be non-negative (a >= 0). | ✅ |
| Preconditions | Input a must not cause overflow when multiplied by WAD_RAY_RATIO (a <= U256_MAX / WAD_RAY_RATIO). | ✅ |
| Postconditions | Result is a * WAD_RAY_RATIO. | ✅ |
| Postconditions | Result is non-negative (result >= 0). | ✅ |
| Verification Consistency | Overflow check: Ensure multiplication does not exceed u256 max value. | ✅ |
| Verification Consistency | Non-negative input: Validate inout non-negative. | ✅ |
| Verification Consistency | Non-negative input: Guarantees the result is non-negative. | ✅ |
function wade_mul |
||
| Preconditions | Inputs a and b must be non-negative (a >= 0, b >= 0). | ✅ |
| Preconditions | The multiplication of a and b must not cause overflow (a <= (U256_MAX - HALF_WAD) / b). | ✅ |
| Postconditions | Result is the product of a and b, rounded half up to the nearest Wad. | ✅ |
| Postconditions | Result is non-negative (result >= 0). | ✅ |
| Verification Conditions | Overflow Check: Ensures the product of a and b does not exceed u256 max value. | ✅ |
| Verification Conditions | Non-Negative Inputs: Validates both inputs are non-negative. | ✅ |
| Verification Conditions | Non-Negative Result: Guarantees the result is non-negative. | ✅ |
function wade_mul |
||
| Preconditions | Denominator b must be non-zero (b > 0). | ✅ |
| Preconditions | Inputs a and b must be non-negative (a >= 0, b >= 0). | ✅ |
| Preconditions | The division must not cause overflow (a <= (U256_MAX - b / 2) / WAD). | ✅ |
| Postconditions | Result is the division of a by b, rounded half up to the nearest Wad. | ✅ |
| Postconditions | Result is non-negative (result >= 0). | ✅ |
| Postconditions | Result is non-negative (result >= 0). | ✅ |
| Verification conditions | Division by Zero Check: Ensures denominator is not zero. | ✅ |
| Verification conditions | Non-Negative Inputs: Validates both inputs are non-negative. | ✅ |
| Verification conditions | Overflow Check: Ensures the division does not exceed u256 max value. | ✅ |
| Verification conditions | Non-Negative Result: Guarantees the result is non-negative. | ✅ |
function ray_div |
||
| Preconditions | Denominator b must be non-zero (b > 0). | ✅ |
| Preconditions | Inputs a and b must be non-negative (a >= 0, b >= 0). | ✅ |
| Preconditions | The division must not cause overflow (a <= (U256_MAX - b / 2) / RAY). | ✅ |
| Postconditions | Result is the division of a by b, rounded half up to the nearest Ray. | ✅ |
| Postconditions | Result is non-negative (result >= 0). | ✅ |
| Verification conditions | Division by Zero Check: Ensures denominator is not zero. | ✅ |
| Verification conditions | Non-Negative Inputs: Validates both inputs are non-negative. | ✅ |
| Verification conditions | Overflow Check: Ensures the division does not exceed u256 max value. | ✅ |
| Verification conditions | Non-Negative Result: Guarantees the result is non-negative. | ✅ |
function ray_mul |
||
| Preconditions | Inputs a and b must be non-negative (a >= 0, b >= 0) | ✅ |
| Postconditions | Result is the product of a and b, rounded half up to the nearest Ray. | ✅ |
| Postconditions | Result is non-negative (result >= 0). | ✅ |
| Verification conditions | Non-Negative Result: Guarantees the result is non-negative. | ✅ |
| Verification conditions | Non-Negative Inputs: Validates both inputs are non-negative. | ✅ |
function ray_to_wad |
||
| Processes stake actions, ensuring the resources and conditions are correct before accepting any stake. Verification is enabled to maintain consistency with the protocol rules. | ✅ | |
| Preconditions | nput a must be non-negative (a >= 0). | ✅ |
| Postconditions | Result is the input a divided by WAD_RAY_RATIO, rounded half up to the nearest Wad. | ✅ |
| Postconditions | Result is non-negative (result >= 0). | ✅ |
| Verification conditions | Non-Negative Result: Guarantees the result is non-negative. | ✅ |
| Verification conditions | Non-Negative Inputs: Validates both inputs are non-negative. | ✅ |
// Specification for wad_to_ray
spec wad_to_ray {
// Preconditions
requires a >= 0; // Ensure non-negative input
requires a <= U256_MAX / WAD_RAY_RATIO; // Ensure no overflow
// Postconditions
ensures result == a * WAD_RAY_RATIO;
ensures result >= 0; // Result should be non-negative
}
// Attach the specification directly to the function
spec wad_mul {
// Preconditions
requires a <= (U256_MAX - HALF_WAD) / b; // Ensure no overflow
requires a >= 0; // Ensure non-negative input
requires b >= 0; // Ensure non-negative input
// Postconditions
ensures result == if (a == 0 || b == 0) { 0 } else { (a * b + HALF_WAD) / WAD };
ensures result >= 0; // Result should be non-negative
}
// Specification for wad_div
spec wad_div {
// Preconditions
requires b > 0; // Denominator must be non-zero
requires a <= (U256_MAX - b / 2) / WAD; // Ensure no overflow
requires a >= 0; // Ensure non-negative input
requires b >= 0; // Ensure non-negative input
// Postconditions
ensures result == if (a == 0) { 0 } else { (a * WAD + b / 2) / b };
ensures result >= 0; // Result should be non-negative
}
// Specification for ray_div
spec ray_div {
// Preconditions
requires b > 0; // Denominator must be non-zero
requires a <= (U256_MAX - b / 2) / RAY; // Ensure no overflow
requires a >= 0; // Ensure non-negative input
requires b >= 0; // Ensure non-negative input
// Postconditions
ensures result == if (a == 0) { 0 } else { (a * RAY + b / 2) / b };
ensures result >= 0; // Result should be non-negative
}
// Specification for ray_mul
spec ray_mul {
// Preconditions
//this does not hold true here
// requires a <= (U256_MAX - HALF_RAY) / b; // Ensure no overflow
requires a >= 0; // Ensure non-negative input
requires b >= 0; // Ensure non-negative input
// Postconditions
ensures result == if (a == 0 || b == 0) { 0 } else { (a * b + HALF_RAY) / RAY };
ensures result >= 0; // Result should be non-negative
}
// Specification for ray_to_wad
spec ray_to_wad {
// Preconditions
requires a >= 0; // Ensure non-negative input
// Postconditions
ensures result == if (a % WAD_RAY_RATIO >= WAD_RAY_RATIO / 2) { a / WAD_RAY_RATIO + 1 } else { a / WAD_RAY_RATIO };
ensures result >= 0; // Result should be non-negative
}
}
aave_math::math_utilis.move| Functionality | Details | Verification Status |
|---|---|---|
function calculate_compounded_interest |
||
| Preconditions | The interest rate must be non-negative. | ✅ |
| Preconditions | The timestamps must be in chronological order (last update timestamp cannot be in the future) | |
| Preconditions | Input a must not cause overflow when multiplied by WAD_RAY_RATIO (a <= U256_MAX / WAD_RAY_RATIO). | ✅ |
| Postconditions | The result is guaranteed to be at least equal to the base ray value(1.0 in ray format) ensures result >= wad_ray_math::ray(); | ✅ |
| Postconditions | When no time has passed, the result equals exactly the base ray (no interest) ensures exp == 0 ==> result == wad_ray_math::ray(); | ✅ |
| Postconditions | When no time has passed, the result equals exactly the base ray (no interest) ensures rate == 0 ==> result == wad_ray_math::ray() | ✅ |
| Postconditions | When the interest rate is zero, the result equals exactly the base ray (no interest) | ✅ |
| Postconditions | When time has passed and the rate is significant, interest will accrue (result > ray) | ✅ |
| Verification Consistency | For special case of exactly 1 time unit passing: Either the result is exactly as calculated by the formula or for very small rates that would round to zero, a minimum interest of 1 is applied. | ✅ |
function pow |
||
| Preconditions | The base must be non-negative. | ✅ |
| Preconditions | The exponent must be non-negative. | ✅ |
| Verification Conditions | base == 0 && exponent > 0 ==> result == 0 should be true mathematically (0 raised to any positive power should be 0) | ❌Acknowledged (Ideal fail) |
| Verification conditions | base > 0 ==> result > 0 should also be true mathematically (any positive number raised to any power should be positive) | ❌Acknowledged (Ideal fail) |
function calculate_linear_interest |
||
| Preconditions | requires rate >= 0. Ensures non-negative interest rate | ✅ |
| Preconditions | equires last_update_timestamp <= timestamp::now_seconds() . Validates timestamp ordering. | ✅ |
| Postconditions | ensures result >= wad_ray_math::ray() | |
| Guarantees minimum interest result | ✅ | |
| Postconditions | ensures last_update_timestamp == timestamp::now_seconds() ==> result == wad_ray_math::ray(). Validates no interest accrual when no time has pass | ✅ |
| Postconditions | ensures rate == 0 ==> result == wad_ray_math::ray() | |
| Validates zero rate case | ✅ | |
| Verification conditions | ensures rate > 0 && last_update_timestamp < timestamp::now_seconds() ==> result … | |
| Verifies correct interest calculation formula | ✅ | |
function percent_mul |
||
| Preconditions | The value input must be non-negative. | ✅ |
| Preconditions | The percentage input must be non-negative. | ✅ |
| Postconditions | The result is guaranteed to be non-negative. | ✅ |
| Postconditions | If either value or percentage is zero, the result must be zero. | ✅ |
function percent_div |
||
| Preconditions | Prevents division by zero by requiring percentage > 0. | ✅ |
| Preconditions | Checks for overflow: value > (U256_MAX - HALF_PERCENTAGE_FACTOR) / PERCENTAGE_FACTOR. |
❌ Fixed https://cantina.xyz/code/b6dada12-d99d-4710-b1d3-e8a69b9af616/findings?created_by=movejay&finding=82 |
| Postconditions | Guarantees non-negative output: result >= 0. |
✅ |
| Postconditions | Validates zero input case: value == 0 ==> result == 0. |
|
| Postconditions | Verifies correct calculation with proper rounding: result == (value * PERCENTAGE_FACTOR + percentage / 2) / percentage. |
✅ |
| Postconditions | Ensures upper bound of result: result <= (value * PERCENTAGE_FACTOR) / percentage + 1. |
✅ |