contracts/lib/forge-std/test/StdMath.t.sol 8.4 K raw
1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.8.0 <0.9.0;
3
4
import {stdMath} from "../src/StdMath.sol";
5
import {Test, stdError} from "../src/Test.sol";
6
7
contract StdMathMock is Test {
8
    function exposed_percentDelta(uint256 a, uint256 b) public pure returns (uint256) {
9
        return stdMath.percentDelta(a, b);
10
    }
11
12
    function exposed_percentDelta(int256 a, int256 b) public pure returns (uint256) {
13
        return stdMath.percentDelta(a, b);
14
    }
15
}
16
17
contract StdMathTest is Test {
18
    function test_GetAbs() external pure {
19
        assertEq(stdMath.abs(-50), 50);
20
        assertEq(stdMath.abs(50), 50);
21
        assertEq(stdMath.abs(-1337), 1337);
22
        assertEq(stdMath.abs(0), 0);
23
24
        assertEq(stdMath.abs(type(int256).min), (type(uint256).max >> 1) + 1);
25
        assertEq(stdMath.abs(type(int256).max), (type(uint256).max >> 1));
26
    }
27
28
    function testFuzz_GetAbs(int256 a) external pure {
29
        uint256 manualAbs = getAbs(a);
30
31
        uint256 abs = stdMath.abs(a);
32
33
        assertEq(abs, manualAbs);
34
    }
35
36
    function test_GetDelta_Uint() external pure {
37
        assertEq(stdMath.delta(uint256(0), uint256(0)), 0);
38
        assertEq(stdMath.delta(uint256(0), uint256(1337)), 1337);
39
        assertEq(stdMath.delta(uint256(0), type(uint64).max), type(uint64).max);
40
        assertEq(stdMath.delta(uint256(0), type(uint128).max), type(uint128).max);
41
        assertEq(stdMath.delta(uint256(0), type(uint256).max), type(uint256).max);
42
43
        assertEq(stdMath.delta(0, uint256(0)), 0);
44
        assertEq(stdMath.delta(1337, uint256(0)), 1337);
45
        assertEq(stdMath.delta(type(uint64).max, uint256(0)), type(uint64).max);
46
        assertEq(stdMath.delta(type(uint128).max, uint256(0)), type(uint128).max);
47
        assertEq(stdMath.delta(type(uint256).max, uint256(0)), type(uint256).max);
48
49
        assertEq(stdMath.delta(1337, uint256(1337)), 0);
50
        assertEq(stdMath.delta(type(uint256).max, type(uint256).max), 0);
51
        assertEq(stdMath.delta(5000, uint256(1250)), 3750);
52
    }
53
54
    function testFuzz_GetDelta_Uint(uint256 a, uint256 b) external pure {
55
        uint256 manualDelta = a > b ? a - b : b - a;
56
57
        uint256 delta = stdMath.delta(a, b);
58
59
        assertEq(delta, manualDelta);
60
    }
61
62
    function test_GetDelta_Int() external pure {
63
        assertEq(stdMath.delta(int256(0), int256(0)), 0);
64
        assertEq(stdMath.delta(int256(0), int256(1337)), 1337);
65
        assertEq(stdMath.delta(int256(0), type(int64).max), type(uint64).max >> 1);
66
        assertEq(stdMath.delta(int256(0), type(int128).max), type(uint128).max >> 1);
67
        assertEq(stdMath.delta(int256(0), type(int256).max), type(uint256).max >> 1);
68
69
        assertEq(stdMath.delta(0, int256(0)), 0);
70
        assertEq(stdMath.delta(1337, int256(0)), 1337);
71
        assertEq(stdMath.delta(type(int64).max, int256(0)), type(uint64).max >> 1);
72
        assertEq(stdMath.delta(type(int128).max, int256(0)), type(uint128).max >> 1);
73
        assertEq(stdMath.delta(type(int256).max, int256(0)), type(uint256).max >> 1);
74
75
        assertEq(stdMath.delta(-0, int256(0)), 0);
76
        assertEq(stdMath.delta(-1337, int256(0)), 1337);
77
        assertEq(stdMath.delta(type(int64).min, int256(0)), (type(uint64).max >> 1) + 1);
78
        assertEq(stdMath.delta(type(int128).min, int256(0)), (type(uint128).max >> 1) + 1);
79
        assertEq(stdMath.delta(type(int256).min, int256(0)), (type(uint256).max >> 1) + 1);
80
81
        assertEq(stdMath.delta(int256(0), -0), 0);
82
        assertEq(stdMath.delta(int256(0), -1337), 1337);
83
        assertEq(stdMath.delta(int256(0), type(int64).min), (type(uint64).max >> 1) + 1);
84
        assertEq(stdMath.delta(int256(0), type(int128).min), (type(uint128).max >> 1) + 1);
85
        assertEq(stdMath.delta(int256(0), type(int256).min), (type(uint256).max >> 1) + 1);
86
87
        assertEq(stdMath.delta(1337, int256(1337)), 0);
88
        assertEq(stdMath.delta(type(int256).max, type(int256).max), 0);
89
        assertEq(stdMath.delta(type(int256).min, type(int256).min), 0);
90
        assertEq(stdMath.delta(type(int256).min, type(int256).max), type(uint256).max);
91
        assertEq(stdMath.delta(5000, int256(1250)), 3750);
92
    }
93
94
    function testFuzz_GetDelta_Int(int256 a, int256 b) external pure {
95
        uint256 absA = getAbs(a);
96
        uint256 absB = getAbs(b);
97
        uint256 absDelta = absA > absB ? absA - absB : absB - absA;
98
99
        uint256 manualDelta;
100
        if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) {
101
            manualDelta = absDelta;
102
        }
103
        // (a < 0 && b >= 0) || (a >= 0 && b < 0)
104
        else {
105
            manualDelta = absA + absB;
106
        }
107
108
        uint256 delta = stdMath.delta(a, b);
109
110
        assertEq(delta, manualDelta);
111
    }
112
113
    function test_GetPercentDelta_Uint() external {
114
        StdMathMock stdMathMock = new StdMathMock();
115
116
        assertEq(stdMath.percentDelta(uint256(0), uint256(1337)), 1e18);
117
        assertEq(stdMath.percentDelta(uint256(0), type(uint64).max), 1e18);
118
        assertEq(stdMath.percentDelta(uint256(0), type(uint128).max), 1e18);
119
        assertEq(stdMath.percentDelta(uint256(0), type(uint192).max), 1e18);
120
121
        assertEq(stdMath.percentDelta(1337, uint256(1337)), 0);
122
        assertEq(stdMath.percentDelta(type(uint192).max, type(uint192).max), 0);
123
        assertEq(stdMath.percentDelta(0, uint256(2500)), 1e18);
124
        assertEq(stdMath.percentDelta(2500, uint256(2500)), 0);
125
        assertEq(stdMath.percentDelta(5000, uint256(2500)), 1e18);
126
        assertEq(stdMath.percentDelta(7500, uint256(2500)), 2e18);
127
128
        vm.expectRevert(stdError.divisionError);
129
        stdMathMock.exposed_percentDelta(uint256(1), 0);
130
    }
131
132
    function testFuzz_GetPercentDelta_Uint(uint192 a, uint192 b) external pure {
133
        vm.assume(b != 0);
134
        uint256 manualDelta = a > b ? a - b : b - a;
135
136
        uint256 manualPercentDelta = manualDelta * 1e18 / b;
137
        uint256 percentDelta = stdMath.percentDelta(a, b);
138
139
        assertEq(percentDelta, manualPercentDelta);
140
    }
141
142
    function test_GetPercentDelta_Int() external {
143
        // We deploy a mock version so we can properly test the revert.
144
        StdMathMock stdMathMock = new StdMathMock();
145
146
        assertEq(stdMath.percentDelta(int256(0), int256(1337)), 1e18);
147
        assertEq(stdMath.percentDelta(int256(0), -1337), 1e18);
148
        assertEq(stdMath.percentDelta(int256(0), type(int64).min), 1e18);
149
        assertEq(stdMath.percentDelta(int256(0), type(int128).min), 1e18);
150
        assertEq(stdMath.percentDelta(int256(0), type(int192).min), 1e18);
151
        assertEq(stdMath.percentDelta(int256(0), type(int64).max), 1e18);
152
        assertEq(stdMath.percentDelta(int256(0), type(int128).max), 1e18);
153
        assertEq(stdMath.percentDelta(int256(0), type(int192).max), 1e18);
154
155
        assertEq(stdMath.percentDelta(1337, int256(1337)), 0);
156
        assertEq(stdMath.percentDelta(type(int192).max, type(int192).max), 0);
157
        assertEq(stdMath.percentDelta(type(int192).min, type(int192).min), 0);
158
159
        assertEq(stdMath.percentDelta(type(int192).min, type(int192).max), 2e18); // rounds the 1 wei diff down
160
        assertEq(stdMath.percentDelta(type(int192).max, type(int192).min), 2e18 - 1); // rounds the 1 wei diff down
161
        assertEq(stdMath.percentDelta(0, int256(2500)), 1e18);
162
        assertEq(stdMath.percentDelta(2500, int256(2500)), 0);
163
        assertEq(stdMath.percentDelta(5000, int256(2500)), 1e18);
164
        assertEq(stdMath.percentDelta(7500, int256(2500)), 2e18);
165
166
        vm.expectRevert(stdError.divisionError);
167
        stdMathMock.exposed_percentDelta(int256(1), 0);
168
    }
169
170
    function testFuzz_GetPercentDelta_Int(int192 a, int192 b) external pure {
171
        vm.assume(b != 0);
172
        uint256 absA = getAbs(a);
173
        uint256 absB = getAbs(b);
174
        uint256 absDelta = absA > absB ? absA - absB : absB - absA;
175
176
        uint256 manualDelta;
177
        if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) {
178
            manualDelta = absDelta;
179
        }
180
        // (a < 0 && b >= 0) || (a >= 0 && b < 0)
181
        else {
182
            manualDelta = absA + absB;
183
        }
184
185
        uint256 manualPercentDelta = manualDelta * 1e18 / absB;
186
        uint256 percentDelta = stdMath.percentDelta(a, b);
187
188
        assertEq(percentDelta, manualPercentDelta);
189
    }
190
191
    /*//////////////////////////////////////////////////////////////////////////
192
                                   HELPERS
193
    //////////////////////////////////////////////////////////////////////////*/
194
195
    function getAbs(int256 a) private pure returns (uint256) {
196
        if (a < 0) {
197
            return a == type(int256).min ? uint256(type(int256).max) + 1 : uint256(-a);
198
        }
199
200
        return uint256(a);
201
    }
202
}