poseidon-solidity-example/lib/forge-std/test/StdUtils.t.sol
lib/forge-std/test/StdUtils.t.solRaw
1// SPDX-License-Identifier: MIT
2pragma solidity >=0.7.0 <0.9.0;
3
4import "../src/Test.sol";
5
6contract StdUtilsMock is StdUtils {
7 // We deploy a mock version so we can properly test expected reverts.
8 function getTokenBalances_(address token, address[] memory addresses)
9 external
10 returns (uint256[] memory balances)
11 {
12 return getTokenBalances(token, addresses);
13 }
14}
15
16contract StdUtilsTest is Test {
17 /*//////////////////////////////////////////////////////////////////////////
18 BOUND UINT
19 //////////////////////////////////////////////////////////////////////////*/
20
21 function testBound() public {
22 assertEq(bound(uint256(5), 0, 4), 0);
23 assertEq(bound(uint256(0), 69, 69), 69);
24 assertEq(bound(uint256(0), 68, 69), 68);
25 assertEq(bound(uint256(10), 150, 190), 174);
26 assertEq(bound(uint256(300), 2800, 3200), 3107);
27 assertEq(bound(uint256(9999), 1337, 6666), 4669);
28 }
29
30 function testBound_WithinRange() public {
31 assertEq(bound(uint256(51), 50, 150), 51);
32 assertEq(bound(uint256(51), 50, 150), bound(bound(uint256(51), 50, 150), 50, 150));
33 assertEq(bound(uint256(149), 50, 150), 149);
34 assertEq(bound(uint256(149), 50, 150), bound(bound(uint256(149), 50, 150), 50, 150));
35 }
36
37 function testBound_EdgeCoverage() public {
38 assertEq(bound(uint256(0), 50, 150), 50);
39 assertEq(bound(uint256(1), 50, 150), 51);
40 assertEq(bound(uint256(2), 50, 150), 52);
41 assertEq(bound(uint256(3), 50, 150), 53);
42 assertEq(bound(type(uint256).max, 50, 150), 150);
43 assertEq(bound(type(uint256).max - 1, 50, 150), 149);
44 assertEq(bound(type(uint256).max - 2, 50, 150), 148);
45 assertEq(bound(type(uint256).max - 3, 50, 150), 147);
46 }
47
48 function testBound_DistributionIsEven(uint256 min, uint256 size) public {
49 size = size % 100 + 1;
50 min = bound(min, UINT256_MAX / 2, UINT256_MAX / 2 + size);
51 uint256 max = min + size - 1;
52 uint256 result;
53
54 for (uint256 i = 1; i <= size * 4; ++i) {
55 // x > max
56 result = bound(max + i, min, max);
57 assertEq(result, min + (i - 1) % size);
58 // x < min
59 result = bound(min - i, min, max);
60 assertEq(result, max - (i - 1) % size);
61 }
62 }
63
64 function testBound(uint256 num, uint256 min, uint256 max) public {
65 if (min > max) (min, max) = (max, min);
66
67 uint256 result = bound(num, min, max);
68
69 assertGe(result, min);
70 assertLe(result, max);
71 assertEq(result, bound(result, min, max));
72 if (num >= min && num <= max) assertEq(result, num);
73 }
74
75 function testBoundUint256Max() public {
76 assertEq(bound(0, type(uint256).max - 1, type(uint256).max), type(uint256).max - 1);
77 assertEq(bound(1, type(uint256).max - 1, type(uint256).max), type(uint256).max);
78 }
79
80 function testCannotBoundMaxLessThanMin() public {
81 vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min."));
82 bound(uint256(5), 100, 10);
83 }
84
85 function testCannotBoundMaxLessThanMin(uint256 num, uint256 min, uint256 max) public {
86 vm.assume(min > max);
87 vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min."));
88 bound(num, min, max);
89 }
90
91 /*//////////////////////////////////////////////////////////////////////////
92 BOUND INT
93 //////////////////////////////////////////////////////////////////////////*/
94
95 function testBoundInt() public {
96 assertEq(bound(-3, 0, 4), 2);
97 assertEq(bound(0, -69, -69), -69);
98 assertEq(bound(0, -69, -68), -68);
99 assertEq(bound(-10, 150, 190), 154);
100 assertEq(bound(-300, 2800, 3200), 2908);
101 assertEq(bound(9999, -1337, 6666), 1995);
102 }
103
104 function testBoundInt_WithinRange() public {
105 assertEq(bound(51, -50, 150), 51);
106 assertEq(bound(51, -50, 150), bound(bound(51, -50, 150), -50, 150));
107 assertEq(bound(149, -50, 150), 149);
108 assertEq(bound(149, -50, 150), bound(bound(149, -50, 150), -50, 150));
109 }
110
111 function testBoundInt_EdgeCoverage() public {
112 assertEq(bound(type(int256).min, -50, 150), -50);
113 assertEq(bound(type(int256).min + 1, -50, 150), -49);
114 assertEq(bound(type(int256).min + 2, -50, 150), -48);
115 assertEq(bound(type(int256).min + 3, -50, 150), -47);
116 assertEq(bound(type(int256).min, 10, 150), 10);
117 assertEq(bound(type(int256).min + 1, 10, 150), 11);
118 assertEq(bound(type(int256).min + 2, 10, 150), 12);
119 assertEq(bound(type(int256).min + 3, 10, 150), 13);
120
121 assertEq(bound(type(int256).max, -50, 150), 150);
122 assertEq(bound(type(int256).max - 1, -50, 150), 149);
123 assertEq(bound(type(int256).max - 2, -50, 150), 148);
124 assertEq(bound(type(int256).max - 3, -50, 150), 147);
125 assertEq(bound(type(int256).max, -50, -10), -10);
126 assertEq(bound(type(int256).max - 1, -50, -10), -11);
127 assertEq(bound(type(int256).max - 2, -50, -10), -12);
128 assertEq(bound(type(int256).max - 3, -50, -10), -13);
129 }
130
131 function testBoundInt_DistributionIsEven(int256 min, uint256 size) public {
132 size = size % 100 + 1;
133 min = bound(min, -int256(size / 2), int256(size - size / 2));
134 int256 max = min + int256(size) - 1;
135 int256 result;
136
137 for (uint256 i = 1; i <= size * 4; ++i) {
138 // x > max
139 result = bound(max + int256(i), min, max);
140 assertEq(result, min + int256((i - 1) % size));
141 // x < min
142 result = bound(min - int256(i), min, max);
143 assertEq(result, max - int256((i - 1) % size));
144 }
145 }
146
147 function testBoundInt(int256 num, int256 min, int256 max) public {
148 if (min > max) (min, max) = (max, min);
149
150 int256 result = bound(num, min, max);
151
152 assertGe(result, min);
153 assertLe(result, max);
154 assertEq(result, bound(result, min, max));
155 if (num >= min && num <= max) assertEq(result, num);
156 }
157
158 function testBoundIntInt256Max() public {
159 assertEq(bound(0, type(int256).max - 1, type(int256).max), type(int256).max - 1);
160 assertEq(bound(1, type(int256).max - 1, type(int256).max), type(int256).max);
161 }
162
163 function testBoundIntInt256Min() public {
164 assertEq(bound(0, type(int256).min, type(int256).min + 1), type(int256).min);
165 assertEq(bound(1, type(int256).min, type(int256).min + 1), type(int256).min + 1);
166 }
167
168 function testCannotBoundIntMaxLessThanMin() public {
169 vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min."));
170 bound(-5, 100, 10);
171 }
172
173 function testCannotBoundIntMaxLessThanMin(int256 num, int256 min, int256 max) public {
174 vm.assume(min > max);
175 vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min."));
176 bound(num, min, max);
177 }
178
179 /*//////////////////////////////////////////////////////////////////////////
180 BYTES TO UINT
181 //////////////////////////////////////////////////////////////////////////*/
182
183 function testBytesToUint() external {
184 bytes memory maxUint = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
185 bytes memory two = hex"02";
186 bytes memory millionEther = hex"d3c21bcecceda1000000";
187
188 assertEq(bytesToUint(maxUint), type(uint256).max);
189 assertEq(bytesToUint(two), 2);
190 assertEq(bytesToUint(millionEther), 1_000_000 ether);
191 }
192
193 function testCannotConvertGT32Bytes() external {
194 bytes memory thirty3Bytes = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
195 vm.expectRevert("StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
196 bytesToUint(thirty3Bytes);
197 }
198
199 /*//////////////////////////////////////////////////////////////////////////
200 COMPUTE CREATE ADDRESS
201 //////////////////////////////////////////////////////////////////////////*/
202
203 function testComputeCreateAddress() external {
204 address deployer = 0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9;
205 uint256 nonce = 14;
206 address createAddress = computeCreateAddress(deployer, nonce);
207 assertEq(createAddress, 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45);
208 }
209
210 /*//////////////////////////////////////////////////////////////////////////
211 COMPUTE CREATE2 ADDRESS
212 //////////////////////////////////////////////////////////////////////////*/
213
214 function testComputeCreate2Address() external {
215 bytes32 salt = bytes32(uint256(31415));
216 bytes32 initcodeHash = keccak256(abi.encode(0x6080));
217 address deployer = 0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9;
218 address create2Address = computeCreate2Address(salt, initcodeHash, deployer);
219 assertEq(create2Address, 0xB147a5d25748fda14b463EB04B111027C290f4d3);
220 }
221}
222
223contract StdUtilsForkTest is Test {
224 /*//////////////////////////////////////////////////////////////////////////
225 GET TOKEN BALANCES
226 //////////////////////////////////////////////////////////////////////////*/
227
228 address internal SHIB = 0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE;
229 address internal SHIB_HOLDER_0 = 0x855F5981e831D83e6A4b4EBFCAdAa68D92333170;
230 address internal SHIB_HOLDER_1 = 0x8F509A90c2e47779cA408Fe00d7A72e359229AdA;
231 address internal SHIB_HOLDER_2 = 0x0e3bbc0D04fF62211F71f3e4C45d82ad76224385;
232
233 address internal USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
234 address internal USDC_HOLDER_0 = 0xDa9CE944a37d218c3302F6B82a094844C6ECEb17;
235 address internal USDC_HOLDER_1 = 0x3e67F4721E6d1c41a015f645eFa37BEd854fcf52;
236
237 function setUp() public {
238 // All tests of the `getTokenBalances` method are fork tests using live contracts.
239 vm.createSelectFork({urlOrAlias: "mainnet", blockNumber: 16_428_900});
240 }
241
242 function testCannotGetTokenBalances_NonTokenContract() external {
243 // We deploy a mock version so we can properly test the revert.
244 StdUtilsMock stdUtils = new StdUtilsMock();
245
246 // The UniswapV2Factory contract has neither a `balanceOf` function nor a fallback function,
247 // so the `balanceOf` call should revert.
248 address token = address(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f);
249 address[] memory addresses = new address[](1);
250 addresses[0] = USDC_HOLDER_0;
251
252 vm.expectRevert("Multicall3: call failed");
253 stdUtils.getTokenBalances_(token, addresses);
254 }
255
256 function testCannotGetTokenBalances_EOA() external {
257 address eoa = vm.addr({privateKey: 1});
258 address[] memory addresses = new address[](1);
259 addresses[0] = USDC_HOLDER_0;
260 vm.expectRevert("StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
261 getTokenBalances(eoa, addresses);
262 }
263
264 function testGetTokenBalances_Empty() external {
265 address[] memory addresses = new address[](0);
266 uint256[] memory balances = getTokenBalances(USDC, addresses);
267 assertEq(balances.length, 0);
268 }
269
270 function testGetTokenBalances_USDC() external {
271 address[] memory addresses = new address[](2);
272 addresses[0] = USDC_HOLDER_0;
273 addresses[1] = USDC_HOLDER_1;
274 uint256[] memory balances = getTokenBalances(USDC, addresses);
275 assertEq(balances[0], 159_000_000_000_000);
276 assertEq(balances[1], 131_350_000_000_000);
277 }
278
279 function testGetTokenBalances_SHIB() external {
280 address[] memory addresses = new address[](3);
281 addresses[0] = SHIB_HOLDER_0;
282 addresses[1] = SHIB_HOLDER_1;
283 addresses[2] = SHIB_HOLDER_2;
284 uint256[] memory balances = getTokenBalances(SHIB, addresses);
285 assertEq(balances[0], 3_323_256_285_484.42e18);
286 assertEq(balances[1], 1_271_702_771_149.99999928e18);
287 assertEq(balances[2], 606_357_106_247e18);
288 }
289}