Skip to content

Commit 3124e2d

Browse files
authored
fix: math helpers explicit tests (#2)
1 parent 25115b2 commit 3124e2d

File tree

5 files changed

+253
-159
lines changed

5 files changed

+253
-159
lines changed

src/contracts/mocks/tests/PercentageMathWrapper.sol

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/contracts/mocks/tests/WadRayMathWrapper.sol

Lines changed: 0 additions & 50 deletions
This file was deleted.

tests/protocol/libraries/math/MathUtils.t.sol

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'forge-std/Test.sol';
55

66
import {MathUtils} from '../../../../src/contracts/protocol/libraries/math/MathUtils.sol';
77

8+
/// forge-config: default.allow_internal_expect_revert = true
89
contract MathUtilsTests is Test {
910
function test_constants() public pure {
1011
assertEq(MathUtils.SECONDS_PER_YEAR, 365 days);
@@ -82,4 +83,28 @@ contract MathUtilsTests is Test {
8283
166666716666676666667666666666666600000000000000
8384
);
8485
}
86+
87+
function testMulDivCeil_WithRemainder() external pure {
88+
assertEq(MathUtils.mulDivCeil(5, 5, 3), 9); // 25 / 3 = 8.333 -> ceil -> 9
89+
}
90+
91+
function testMulDivCeil_NoRemainder() external pure {
92+
assertEq(MathUtils.mulDivCeil(12, 6, 4), 18); // 72 / 4 = 18, no ceil
93+
}
94+
95+
function testMulDivCeil_ZeroAOrB() external pure {
96+
assertEq(MathUtils.mulDivCeil(0, 10, 5), 0);
97+
assertEq(MathUtils.mulDivCeil(10, 0, 5), 0);
98+
}
99+
100+
function testMulDivCeil_RevertOnDivByZero() external {
101+
vm.expectRevert();
102+
MathUtils.mulDivCeil(10, 10, 0);
103+
}
104+
105+
function testMulDivCeil_RevertOnOverflow() external {
106+
uint256 max = type(uint256).max;
107+
vm.expectRevert();
108+
MathUtils.mulDivCeil(max, 2, 1); // max * 2 will overflow
109+
}
85110
}

tests/protocol/libraries/math/PercentageMath.t.sol

Lines changed: 88 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,56 +4,118 @@ pragma solidity ^0.8.0;
44
import 'forge-std/Test.sol';
55

66
import {PercentageMath} from '../../../../src/contracts/protocol/libraries/math/PercentageMath.sol';
7-
import {PercentageMathWrapper} from '../../../../src/contracts/mocks/tests/PercentageMathWrapper.sol';
87

8+
/// forge-config: default.allow_internal_expect_revert = true
99
contract PercentageMathTests is Test {
10-
PercentageMathWrapper internal w;
11-
12-
function setUp() public {
13-
w = new PercentageMathWrapper();
14-
}
15-
16-
function test_constants() public view {
17-
assertEq(w.PERCENTAGE_FACTOR(), 1e4, 'percentage factor');
18-
assertEq(w.HALF_PERCENTAGE_FACTOR(), 0.5e4, 'half wad');
10+
function test_constants() public pure {
11+
assertEq(PercentageMath.PERCENTAGE_FACTOR, 1e4, 'percentage factor');
12+
assertEq(PercentageMath.HALF_PERCENTAGE_FACTOR, 0.5e4, 'half wad');
1913
}
2014

2115
function test_percentMul_fuzz(uint256 value, uint256 percentage) public {
2216
if (
2317
(percentage == 0 ||
24-
(value > (type(uint256).max - w.HALF_PERCENTAGE_FACTOR()) / percentage) == false) == false
18+
(value > (type(uint256).max - PercentageMath.HALF_PERCENTAGE_FACTOR) / percentage) ==
19+
false) == false
2520
) {
2621
vm.expectRevert();
27-
w.percentMul(value, percentage);
22+
PercentageMath.percentMul(value, percentage);
2823
} else {
2924
assertEq(
30-
w.percentMul(value, percentage),
31-
((value * percentage) + w.HALF_PERCENTAGE_FACTOR()) / (w.PERCENTAGE_FACTOR())
25+
PercentageMath.percentMul(value, percentage),
26+
((value * percentage) + PercentageMath.HALF_PERCENTAGE_FACTOR) /
27+
(PercentageMath.PERCENTAGE_FACTOR)
3228
);
3329
}
3430
}
3531

3632
function test_percentDiv_fuzz(uint256 value, uint256 percentage) public {
37-
if (percentage == 0 || value > (type(uint256).max - (percentage / 2)) / w.PERCENTAGE_FACTOR()) {
33+
if (
34+
percentage == 0 ||
35+
value > (type(uint256).max - (percentage / 2)) / PercentageMath.PERCENTAGE_FACTOR
36+
) {
3837
vm.expectRevert();
39-
w.percentDiv(value, percentage);
38+
PercentageMath.percentDiv(value, percentage);
4039
} else {
4140
assertEq(
42-
w.percentDiv(value, percentage),
43-
((value * w.PERCENTAGE_FACTOR()) + (percentage / 2)) / percentage
41+
PercentageMath.percentDiv(value, percentage),
42+
((value * PercentageMath.PERCENTAGE_FACTOR) + (percentage / 2)) / percentage
4443
);
4544
}
4645
}
4746

48-
function test_percentMul() public view {
49-
assertEq(w.percentMul(1e18, 50_00), 0.5e18);
50-
assertEq(w.percentMul(14.2515e18, 74_42), 10.605966300000000000e18);
51-
assertEq(w.percentMul(9087312e27, 13_33), 1211338689600000000000000000000000);
47+
function test_percentMul() external pure {
48+
assertEq(PercentageMath.percentMul(1e18, 50_00), 0.5e18);
49+
assertEq(PercentageMath.percentMul(14.2515e18, 74_42), 10.605966300000000000e18);
50+
assertEq(PercentageMath.percentMul(9087312e27, 13_33), 1211338689600000000000000000000000);
51+
}
52+
53+
function test_percentDiv() external pure {
54+
assertEq(PercentageMath.percentDiv(1e18, 50_00), 2e18);
55+
assertEq(PercentageMath.percentDiv(14.2515e18, 74_42), 19.150094060736361193e18);
56+
assertEq(PercentageMath.percentDiv(9087312e27, 13_33), 68171882970742685671417854463615904);
57+
}
58+
59+
function testPercentMulCeil_Exact() external pure {
60+
uint256 result = PercentageMath.percentMulCeil(100 ether, PercentageMath.PERCENTAGE_FACTOR); // 100%
61+
assertEq(result, 100 ether);
62+
}
63+
64+
function testPercentMulCeil_WithRoundingUp() external pure {
65+
uint256 result = PercentageMath.percentMulCeil(1, 1); // (1 * 1) / 10_000 = 0.0001 => ceil to 1
66+
assertEq(result, 1);
67+
}
68+
69+
function testPercentMulCeil_ZeroValueOrPercent() external pure {
70+
assertEq(PercentageMath.percentMulCeil(0, 100), 0);
71+
assertEq(PercentageMath.percentMulCeil(100, 0), 0);
72+
}
73+
74+
function testPercentMulCeil_RevertOnOverflow() public {
75+
uint256 max = type(uint256).max;
76+
vm.expectRevert();
77+
PercentageMath.percentMulCeil(max, 2);
78+
}
79+
80+
function testPercentMulFloor_Exact() external pure {
81+
uint256 result = PercentageMath.percentMulFloor(100 ether, PercentageMath.PERCENTAGE_FACTOR); // 100%
82+
assertEq(result, 100 ether);
83+
}
84+
85+
function testPercentMulFloor_WithTruncation() external pure {
86+
uint256 result = PercentageMath.percentMulFloor(1, 1); // (1 * 1) / 10_000 = 0.0001 => floor to 0
87+
assertEq(result, 0);
88+
}
89+
90+
function testPercentMulFloor_ZeroInputs() external pure {
91+
assertEq(PercentageMath.percentMulFloor(0, 1234), 0);
92+
assertEq(PercentageMath.percentMulFloor(1234, 0), 0);
93+
}
94+
95+
function testPercentMulFloor_RevertOnOverflow() external {
96+
uint256 max = type(uint256).max;
97+
vm.expectRevert();
98+
PercentageMath.percentMulFloor(max, 2);
99+
}
100+
101+
function testPercentDivCeil_Exact() external pure {
102+
uint256 result = PercentageMath.percentDivCeil(100 ether, PercentageMath.PERCENTAGE_FACTOR); // 100%
103+
assertEq(result, 100 ether);
104+
}
105+
106+
function testPercentDivCeil_WithCeilNeeded() external pure {
107+
uint256 result = PercentageMath.percentDivCeil(5, 3); // (5 * 10_000) / 3 = 16666.6... => ceil to 16667
108+
assertEq(result, 16667);
109+
}
110+
111+
function testPercentDivCeil_RevertOnDivByZero() public {
112+
vm.expectRevert();
113+
PercentageMath.percentDivCeil(1234, 0);
52114
}
53115

54-
function test_percentDiv() public view {
55-
assertEq(w.percentDiv(1e18, 50_00), 2e18);
56-
assertEq(w.percentDiv(14.2515e18, 74_42), 19.150094060736361193e18);
57-
assertEq(w.percentDiv(9087312e27, 13_33), 68171882970742685671417854463615904);
116+
function testPercentDivCeil_RevertOnOverflow() public {
117+
uint256 max = type(uint256).max;
118+
vm.expectRevert();
119+
PercentageMath.percentDivCeil(max, 1); // max * PERCENTAGE_FACTOR will overflow
58120
}
59121
}

0 commit comments

Comments
 (0)