Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fullmath tests #609

Merged
merged 3 commits into from
Apr 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions test/libraries/FullMath.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
pragma solidity ^0.8.19;

import {Test} from "forge-std/Test.sol";
import {FullMath} from "src/libraries/FullMath.sol";
import {FullMath} from "../../src/libraries/FullMath.sol";

contract FullMathTest is Test {
using FullMath for uint256;

uint256 constant Q128 = 2 ** 128;
uint256 constant MAX_UINT256 = type(uint256).max;

function test_mulDiv_revertsWith0Denominator(uint256 x, uint256 y) public {
function test_fuzz_mulDiv_revertsWith0Denominator(uint256 x, uint256 y) public {
vm.expectRevert();
x.mulDiv(y, 0);
}
Expand Down Expand Up @@ -49,14 +49,14 @@ contract FullMathTest is Test {
assertEq(Q128.mulDiv(1000 * Q128, 3000 * Q128), result);
}

function test_mulDiv_fuzz(uint256 x, uint256 y, uint256 d) public {
function test_fuzz_mulDiv(uint256 x, uint256 y, uint256 d) public {
vm.assume(d != 0);
vm.assume(y != 0);
vm.assume(x <= type(uint256).max / y);
assertEq(FullMath.mulDiv(x, y, d), x * y / d);
}

function test_mulDivRoundingUp_revertsWith0Denominator(uint256 x, uint256 y) public {
function test_fuzz_mulDivRoundingUp_revertsWith0Denominator(uint256 x, uint256 y) public {
vm.expectRevert();
x.mulDivRoundingUp(y, 0);
}
Expand Down Expand Up @@ -94,7 +94,7 @@ contract FullMathTest is Test {
);
}

function test_mulDivRoundingUp_fuzz(uint256 x, uint256 y, uint256 d) public {
function test_fuzz_mulDivRoundingUp(uint256 x, uint256 y, uint256 d) public {
vm.assume(d != 0);
vm.assume(y != 0);
vm.assume(x <= type(uint256).max / y);
Expand All @@ -103,7 +103,7 @@ contract FullMathTest is Test {
assertTrue(result == numerator / d || result == numerator / d + 1);
}

function test_mulDivRounding(uint256 x, uint256 y, uint256 d) public {
function test_invariant_mulDivRounding(uint256 x, uint256 y, uint256 d) public {
unchecked {
vm.assume(d > 0);
vm.assume(!resultOverflows(x, y, d));
Expand All @@ -120,7 +120,7 @@ contract FullMathTest is Test {
}
}

function test_mulDiv_recomputed(uint256 x, uint256 y, uint256 d) public {
function test_invariant_mulDiv(uint256 x, uint256 y, uint256 d) public {
unchecked {
vm.assume(d > 0);
vm.assume(!resultOverflows(x, y, d));
Expand All @@ -141,7 +141,7 @@ contract FullMathTest is Test {
}
}

function checkMulDivRoundingUp(uint256 x, uint256 y, uint256 d) external {
function test_invariant_mulDivRoundingUp(uint256 x, uint256 y, uint256 d) external {
unchecked {
vm.assume(d > 0);
vm.assume(!resultOverflows(x, y, d));
Expand All @@ -151,7 +151,9 @@ contract FullMathTest is Test {
return;
}

// recompute x and y via mulDiv of the result of floor(x*y/d), should always be less than original inputs by < d
vm.assume(!resultOverflows(z, d, y));
vm.assume(!resultOverflows(z, d, x));
// recompute x and y via mulDiv of the result of ceil(x*y/d), should always be greater than original inputs by < d
uint256 x2 = FullMath.mulDiv(z, d, y);
uint256 y2 = FullMath.mulDiv(z, d, x);
assertGe(x2, x);
Expand All @@ -162,7 +164,7 @@ contract FullMathTest is Test {
}
}

function testResultOverflowsHelper() public {
function test_resultOverflows_helper() public {
assertFalse(resultOverflows(0, 0, 1));
assertFalse(resultOverflows(1, 0, 1));
assertFalse(resultOverflows(0, 1, 1));
Expand All @@ -182,7 +184,7 @@ contract FullMathTest is Test {
return false;
}

// Iif intermediate multiplication doesn't overflow, there's no overflow
// If intermediate multiplication doesn't overflow, there's no overflow
if (x <= type(uint256).max / y) return false;

uint256 remainder = mulmod(x, y, type(uint256).max);
Expand Down
Loading