poseidon-solidity-example/lib/forge-std/test/StdCheats.t.sol
lib/forge-std/test/StdCheats.t.solRaw
1// SPDX-License-Identifier: MIT
2pragma solidity >=0.7.0 <0.9.0;
3
4import "../src/StdCheats.sol";
5import "../src/Test.sol";
6import "../src/StdJson.sol";
7
8contract StdCheatsTest is Test {
9 Bar test;
10
11 using stdJson for string;
12
13 function setUp() public {
14 test = new Bar();
15 }
16
17 function testSkip() public {
18 vm.warp(100);
19 skip(25);
20 assertEq(block.timestamp, 125);
21 }
22
23 function testRewind() public {
24 vm.warp(100);
25 rewind(25);
26 assertEq(block.timestamp, 75);
27 }
28
29 function testHoax() public {
30 hoax(address(1337));
31 test.bar{value: 100}(address(1337));
32 }
33
34 function testHoaxOrigin() public {
35 hoax(address(1337), address(1337));
36 test.origin{value: 100}(address(1337));
37 }
38
39 function testHoaxDifferentAddresses() public {
40 hoax(address(1337), address(7331));
41 test.origin{value: 100}(address(1337), address(7331));
42 }
43
44 function testStartHoax() public {
45 startHoax(address(1337));
46 test.bar{value: 100}(address(1337));
47 test.bar{value: 100}(address(1337));
48 vm.stopPrank();
49 test.bar(address(this));
50 }
51
52 function testStartHoaxOrigin() public {
53 startHoax(address(1337), address(1337));
54 test.origin{value: 100}(address(1337));
55 test.origin{value: 100}(address(1337));
56 vm.stopPrank();
57 test.bar(address(this));
58 }
59
60 function testChangePrank() public {
61 vm.startPrank(address(1337));
62 test.bar(address(1337));
63 changePrank(address(0xdead));
64 test.bar(address(0xdead));
65 changePrank(address(1337));
66 test.bar(address(1337));
67 vm.stopPrank();
68 }
69
70 function testMakeAddrEquivalence() public {
71 (address addr,) = makeAddrAndKey("1337");
72 assertEq(makeAddr("1337"), addr);
73 }
74
75 function testMakeAddrSigning() public {
76 (address addr, uint256 key) = makeAddrAndKey("1337");
77 bytes32 hash = keccak256("some_message");
78
79 (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash);
80 assertEq(ecrecover(hash, v, r, s), addr);
81 }
82
83 function testDeal() public {
84 deal(address(this), 1 ether);
85 assertEq(address(this).balance, 1 ether);
86 }
87
88 function testDealToken() public {
89 Bar barToken = new Bar();
90 address bar = address(barToken);
91 deal(bar, address(this), 10000e18);
92 assertEq(barToken.balanceOf(address(this)), 10000e18);
93 }
94
95 function testDealTokenAdjustTS() public {
96 Bar barToken = new Bar();
97 address bar = address(barToken);
98 deal(bar, address(this), 10000e18, true);
99 assertEq(barToken.balanceOf(address(this)), 10000e18);
100 assertEq(barToken.totalSupply(), 20000e18);
101 deal(bar, address(this), 0, true);
102 assertEq(barToken.balanceOf(address(this)), 0);
103 assertEq(barToken.totalSupply(), 10000e18);
104 }
105
106 function testDeployCode() public {
107 address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""));
108 assertEq(string(getCode(deployed)), string(getCode(address(test))));
109 }
110
111 function testDeployCodeNoArgs() public {
112 address deployed = deployCode("StdCheats.t.sol:Bar");
113 assertEq(string(getCode(deployed)), string(getCode(address(test))));
114 }
115
116 function testDeployCodeVal() public {
117 address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""), 1 ether);
118 assertEq(string(getCode(deployed)), string(getCode(address(test))));
119 assertEq(deployed.balance, 1 ether);
120 }
121
122 function testDeployCodeValNoArgs() public {
123 address deployed = deployCode("StdCheats.t.sol:Bar", 1 ether);
124 assertEq(string(getCode(deployed)), string(getCode(address(test))));
125 assertEq(deployed.balance, 1 ether);
126 }
127
128 // We need this so we can call "this.deployCode" rather than "deployCode" directly
129 function deployCodeHelper(string memory what) external {
130 deployCode(what);
131 }
132
133 function testDeployCodeFail() public {
134 vm.expectRevert(bytes("StdCheats deployCode(string): Deployment failed."));
135 this.deployCodeHelper("StdCheats.t.sol:RevertingContract");
136 }
137
138 function getCode(address who) internal view returns (bytes memory o_code) {
139 /// @solidity memory-safe-assembly
140 assembly {
141 // retrieve the size of the code, this needs assembly
142 let size := extcodesize(who)
143 // allocate output byte array - this could also be done without assembly
144 // by using o_code = new bytes(size)
145 o_code := mload(0x40)
146 // new "memory end" including padding
147 mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
148 // store length in memory
149 mstore(o_code, size)
150 // actually retrieve the code, this needs assembly
151 extcodecopy(who, add(o_code, 0x20), 0, size)
152 }
153 }
154
155 function testDeriveRememberKey() public {
156 string memory mnemonic = "test test test test test test test test test test test junk";
157
158 (address deployer, uint256 privateKey) = deriveRememberKey(mnemonic, 0);
159 assertEq(deployer, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
160 assertEq(privateKey, 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80);
161 }
162
163 function testBytesToUint() public {
164 assertEq(3, bytesToUint_test(hex"03"));
165 assertEq(2, bytesToUint_test(hex"02"));
166 assertEq(255, bytesToUint_test(hex"ff"));
167 assertEq(29625, bytesToUint_test(hex"73b9"));
168 }
169
170 function testParseJsonTxDetail() public {
171 string memory root = vm.projectRoot();
172 string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
173 string memory json = vm.readFile(path);
174 bytes memory transactionDetails = json.parseRaw(".transactions[0].tx");
175 RawTx1559Detail memory rawTxDetail = abi.decode(transactionDetails, (RawTx1559Detail));
176 Tx1559Detail memory txDetail = rawToConvertedEIP1559Detail(rawTxDetail);
177 assertEq(txDetail.from, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
178 assertEq(txDetail.to, 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512);
179 assertEq(
180 txDetail.data,
181 hex"23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004"
182 );
183 assertEq(txDetail.nonce, 3);
184 assertEq(txDetail.txType, 2);
185 assertEq(txDetail.gas, 29625);
186 assertEq(txDetail.value, 0);
187 }
188
189 function testReadEIP1559Transaction() public view {
190 string memory root = vm.projectRoot();
191 string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
192 uint256 index = 0;
193 Tx1559 memory transaction = readTx1559(path, index);
194 transaction;
195 }
196
197 function testReadEIP1559Transactions() public view {
198 string memory root = vm.projectRoot();
199 string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
200 Tx1559[] memory transactions = readTx1559s(path);
201 transactions;
202 }
203
204 function testReadReceipt() public {
205 string memory root = vm.projectRoot();
206 string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
207 uint256 index = 5;
208 Receipt memory receipt = readReceipt(path, index);
209 assertEq(
210 receipt.logsBloom,
211 hex"00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100"
212 );
213 }
214
215 function testReadReceipts() public view {
216 string memory root = vm.projectRoot();
217 string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
218 Receipt[] memory receipts = readReceipts(path);
219 receipts;
220 }
221
222 function testGasMeteringModifier() public {
223 uint256 gas_start_normal = gasleft();
224 addInLoop();
225 uint256 gas_used_normal = gas_start_normal - gasleft();
226
227 uint256 gas_start_single = gasleft();
228 addInLoopNoGas();
229 uint256 gas_used_single = gas_start_single - gasleft();
230
231 uint256 gas_start_double = gasleft();
232 addInLoopNoGasNoGas();
233 uint256 gas_used_double = gas_start_double - gasleft();
234
235 emit log_named_uint("Normal gas", gas_used_normal);
236 emit log_named_uint("Single modifier gas", gas_used_single);
237 emit log_named_uint("Double modifier gas", gas_used_double);
238 assertTrue(gas_used_double + gas_used_single < gas_used_normal);
239 }
240
241 function addInLoop() internal pure returns (uint256) {
242 uint256 b;
243 for (uint256 i; i < 10000; i++) {
244 b += i;
245 }
246 return b;
247 }
248
249 function addInLoopNoGas() internal noGasMetering returns (uint256) {
250 return addInLoop();
251 }
252
253 function addInLoopNoGasNoGas() internal noGasMetering returns (uint256) {
254 return addInLoopNoGas();
255 }
256
257 function bytesToUint_test(bytes memory b) private pure returns (uint256) {
258 uint256 number;
259 for (uint256 i = 0; i < b.length; i++) {
260 number = number + uint256(uint8(b[i])) * (2 ** (8 * (b.length - (i + 1))));
261 }
262 return number;
263 }
264
265 function testAssumeNoPrecompiles(address addr) external {
266 assumeNoPrecompiles(addr, getChain("optimism_goerli").chainId);
267 assertTrue(
268 addr < address(1) || (addr > address(9) && addr < address(0x4200000000000000000000000000000000000000))
269 || addr > address(0x4200000000000000000000000000000000000800)
270 );
271 }
272
273 function testAssumePayable() external {
274 // all should revert since these addresses are not payable
275
276 // VM address
277 vm.expectRevert();
278 assumePayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
279
280 // Console address
281 vm.expectRevert();
282 assumePayable(0x000000000000000000636F6e736F6c652e6c6f67);
283
284 // Create2Deployer
285 vm.expectRevert();
286 assumePayable(0x4e59b44847b379578588920cA78FbF26c0B4956C);
287 }
288
289 function testAssumePayable(address addr) external {
290 assumePayable(addr);
291 assertTrue(
292 addr != 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D && addr != 0x000000000000000000636F6e736F6c652e6c6f67
293 && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
294 );
295 }
296}
297
298contract Bar {
299 constructor() payable {
300 /// `DEAL` STDCHEAT
301 totalSupply = 10000e18;
302 balanceOf[address(this)] = totalSupply;
303 }
304
305 /// `HOAX` STDCHEATS
306 function bar(address expectedSender) public payable {
307 require(msg.sender == expectedSender, "!prank");
308 }
309
310 function origin(address expectedSender) public payable {
311 require(msg.sender == expectedSender, "!prank");
312 require(tx.origin == expectedSender, "!prank");
313 }
314
315 function origin(address expectedSender, address expectedOrigin) public payable {
316 require(msg.sender == expectedSender, "!prank");
317 require(tx.origin == expectedOrigin, "!prank");
318 }
319
320 /// `DEAL` STDCHEAT
321 mapping(address => uint256) public balanceOf;
322 uint256 public totalSupply;
323}
324
325contract RevertingContract {
326 constructor() {
327 revert();
328 }
329}