contracts/lib/forge-std/src/StdCheats.sol 31.1 K raw
1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3
4
pragma experimental ABIEncoderV2;
5
6
import {StdStorage, stdStorage} from "./StdStorage.sol";
7
import {console2} from "./console2.sol";
8
import {Vm} from "./Vm.sol";
9
10
abstract contract StdCheatsSafe {
11
    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
12
13
    uint256 private constant UINT256_MAX =
14
        115792089237316195423570985008687907853269984665640564039457584007913129639935;
15
16
    bool private gasMeteringOff;
17
18
    // Data structures to parse Transaction objects from the broadcast artifact
19
    // that conform to EIP1559. The Raw structs is what is parsed from the JSON
20
    // and then converted to the one that is used by the user for better UX.
21
22
    struct RawTx1559 {
23
        string[] arguments;
24
        address contractAddress;
25
        string contractName;
26
        // json value name = function
27
        string functionSig;
28
        bytes32 hash;
29
        // json value name = tx
30
        RawTx1559Detail txDetail;
31
        // json value name = type
32
        string opcode;
33
    }
34
35
    struct RawTx1559Detail {
36
        AccessList[] accessList;
37
        bytes data;
38
        address from;
39
        bytes gas;
40
        bytes nonce;
41
        address to;
42
        bytes txType;
43
        bytes value;
44
    }
45
46
    struct Tx1559 {
47
        string[] arguments;
48
        address contractAddress;
49
        string contractName;
50
        string functionSig;
51
        bytes32 hash;
52
        Tx1559Detail txDetail;
53
        string opcode;
54
    }
55
56
    struct Tx1559Detail {
57
        AccessList[] accessList;
58
        bytes data;
59
        address from;
60
        uint256 gas;
61
        uint256 nonce;
62
        address to;
63
        uint256 txType;
64
        uint256 value;
65
    }
66
67
    // Data structures to parse Transaction objects from the broadcast artifact
68
    // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
69
    // and then converted to the one that is used by the user for better UX.
70
71
    struct TxLegacy {
72
        string[] arguments;
73
        address contractAddress;
74
        string contractName;
75
        string functionSig;
76
        string hash;
77
        string opcode;
78
        TxDetailLegacy transaction;
79
    }
80
81
    struct TxDetailLegacy {
82
        AccessList[] accessList;
83
        uint256 chainId;
84
        bytes data;
85
        address from;
86
        uint256 gas;
87
        uint256 gasPrice;
88
        bytes32 hash;
89
        uint256 nonce;
90
        bytes1 opcode;
91
        bytes32 r;
92
        bytes32 s;
93
        uint256 txType;
94
        address to;
95
        uint8 v;
96
        uint256 value;
97
    }
98
99
    struct AccessList {
100
        address accessAddress;
101
        bytes32[] storageKeys;
102
    }
103
104
    // Data structures to parse Receipt objects from the broadcast artifact.
105
    // The Raw structs is what is parsed from the JSON
106
    // and then converted to the one that is used by the user for better UX.
107
108
    struct RawReceipt {
109
        bytes32 blockHash;
110
        bytes blockNumber;
111
        address contractAddress;
112
        bytes cumulativeGasUsed;
113
        bytes effectiveGasPrice;
114
        address from;
115
        bytes gasUsed;
116
        RawReceiptLog[] logs;
117
        bytes logsBloom;
118
        bytes status;
119
        address to;
120
        bytes32 transactionHash;
121
        bytes transactionIndex;
122
    }
123
124
    struct Receipt {
125
        bytes32 blockHash;
126
        uint256 blockNumber;
127
        address contractAddress;
128
        uint256 cumulativeGasUsed;
129
        uint256 effectiveGasPrice;
130
        address from;
131
        uint256 gasUsed;
132
        ReceiptLog[] logs;
133
        bytes logsBloom;
134
        uint256 status;
135
        address to;
136
        bytes32 transactionHash;
137
        uint256 transactionIndex;
138
    }
139
140
    // Data structures to parse the entire broadcast artifact, assuming the
141
    // transactions conform to EIP1559.
142
143
    struct EIP1559ScriptArtifact {
144
        string[] libraries;
145
        string path;
146
        string[] pending;
147
        Receipt[] receipts;
148
        uint256 timestamp;
149
        Tx1559[] transactions;
150
        TxReturn[] txReturns;
151
    }
152
153
    struct RawEIP1559ScriptArtifact {
154
        string[] libraries;
155
        string path;
156
        string[] pending;
157
        RawReceipt[] receipts;
158
        TxReturn[] txReturns;
159
        uint256 timestamp;
160
        RawTx1559[] transactions;
161
    }
162
163
    struct RawReceiptLog {
164
        // json value = address
165
        address logAddress;
166
        bytes32 blockHash;
167
        bytes blockNumber;
168
        bytes data;
169
        bytes logIndex;
170
        bool removed;
171
        bytes32[] topics;
172
        bytes32 transactionHash;
173
        bytes transactionIndex;
174
        bytes transactionLogIndex;
175
    }
176
177
    struct ReceiptLog {
178
        // json value = address
179
        address logAddress;
180
        bytes32 blockHash;
181
        uint256 blockNumber;
182
        bytes data;
183
        uint256 logIndex;
184
        bytes32[] topics;
185
        uint256 transactionIndex;
186
        uint256 transactionLogIndex;
187
        bool removed;
188
    }
189
190
    struct TxReturn {
191
        string internalType;
192
        string value;
193
    }
194
195
    struct Account {
196
        address addr;
197
        uint256 key;
198
    }
199
200
    enum AddressType {
201
        Payable,
202
        NonPayable,
203
        ZeroAddress,
204
        Precompile,
205
        ForgeAddress
206
    }
207
208
    // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
209
    function assumeNotBlacklisted(address token, address addr) internal view virtual {
210
        // Nothing to check if `token` is not a contract.
211
        uint256 tokenCodeSize;
212
        assembly {
213
            tokenCodeSize := extcodesize(token)
214
        }
215
        require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
216
217
        bool success;
218
        bytes memory returnData;
219
220
        // 4-byte selector for `isBlacklisted(address)`, used by USDC.
221
        (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr));
222
        vm.assume(!success || abi.decode(returnData, (bool)) == false);
223
224
        // 4-byte selector for `isBlackListed(address)`, used by USDT.
225
        (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr));
226
        vm.assume(!success || abi.decode(returnData, (bool)) == false);
227
    }
228
229
    // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
230
    // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for
231
    // backwards compatibility, since this name was used in the original PR which already has
232
    // a release. This function can be removed in a future release once we want a breaking change.
233
    function assumeNoBlacklisted(address token, address addr) internal view virtual {
234
        assumeNotBlacklisted(token, addr);
235
    }
236
237
    function assumeAddressIsNot(address addr, AddressType addressType) internal virtual {
238
        if (addressType == AddressType.Payable) {
239
            assumeNotPayable(addr);
240
        } else if (addressType == AddressType.NonPayable) {
241
            assumePayable(addr);
242
        } else if (addressType == AddressType.ZeroAddress) {
243
            assumeNotZeroAddress(addr);
244
        } else if (addressType == AddressType.Precompile) {
245
            assumeNotPrecompile(addr);
246
        } else if (addressType == AddressType.ForgeAddress) {
247
            assumeNotForgeAddress(addr);
248
        }
249
    }
250
251
    function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual {
252
        assumeAddressIsNot(addr, addressType1);
253
        assumeAddressIsNot(addr, addressType2);
254
    }
255
256
    function assumeAddressIsNot(
257
        address addr,
258
        AddressType addressType1,
259
        AddressType addressType2,
260
        AddressType addressType3
261
    ) internal virtual {
262
        assumeAddressIsNot(addr, addressType1);
263
        assumeAddressIsNot(addr, addressType2);
264
        assumeAddressIsNot(addr, addressType3);
265
    }
266
267
    function assumeAddressIsNot(
268
        address addr,
269
        AddressType addressType1,
270
        AddressType addressType2,
271
        AddressType addressType3,
272
        AddressType addressType4
273
    ) internal virtual {
274
        assumeAddressIsNot(addr, addressType1);
275
        assumeAddressIsNot(addr, addressType2);
276
        assumeAddressIsNot(addr, addressType3);
277
        assumeAddressIsNot(addr, addressType4);
278
    }
279
280
    // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to
281
    // `addr` and checking the `success` return value.
282
    // NOTE: This function may result in state changes depending on the fallback/receive logic
283
    // implemented by `addr`, which should be taken into account when this function is used.
284
    function _isPayable(address addr) private returns (bool) {
285
        require(
286
            addr.balance < UINT256_MAX,
287
            "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds"
288
        );
289
        uint256 origBalanceTest = address(this).balance;
290
        uint256 origBalanceAddr = address(addr).balance;
291
292
        vm.deal(address(this), 1);
293
        (bool success,) = payable(addr).call{value: 1}("");
294
295
        // reset balances
296
        vm.deal(address(this), origBalanceTest);
297
        vm.deal(addr, origBalanceAddr);
298
299
        return success;
300
    }
301
302
    // NOTE: This function may result in state changes depending on the fallback/receive logic
303
    // implemented by `addr`, which should be taken into account when this function is used. See the
304
    // `_isPayable` method for more information.
305
    function assumePayable(address addr) internal virtual {
306
        vm.assume(_isPayable(addr));
307
    }
308
309
    function assumeNotPayable(address addr) internal virtual {
310
        vm.assume(!_isPayable(addr));
311
    }
312
313
    function assumeNotZeroAddress(address addr) internal pure virtual {
314
        vm.assume(addr != address(0));
315
    }
316
317
    function assumeNotPrecompile(address addr) internal pure virtual {
318
        assumeNotPrecompile(addr, _pureChainId());
319
    }
320
321
    function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual {
322
        // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific
323
        // address), but the same rationale for excluding them applies so we include those too.
324
325
        // These are reserved by Ethereum and may be on all EVM-compatible chains.
326
        vm.assume(addr < address(0x1) || addr > address(0xff));
327
328
        // forgefmt: disable-start
329
        if (chainId == 10 || chainId == 420) {
330
            // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
331
            vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));
332
        } else if (chainId == 42161 || chainId == 421613) {
333
            // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
334
            vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));
335
        } else if (chainId == 43114 || chainId == 43113) {
336
            // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
337
            vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));
338
            vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));
339
            vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));
340
        }
341
        // forgefmt: disable-end
342
    }
343
344
    function assumeNotForgeAddress(address addr) internal pure virtual {
345
        // vm, console, and Create2Deployer addresses
346
        vm.assume(
347
            addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
348
                && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
349
        );
350
    }
351
352
    function assumeUnusedAddress(address addr) internal view virtual {
353
        uint256 size;
354
        assembly {
355
            size := extcodesize(addr)
356
        }
357
        vm.assume(size == 0);
358
359
        assumeNotPrecompile(addr);
360
        assumeNotZeroAddress(addr);
361
        assumeNotForgeAddress(addr);
362
    }
363
364
    function readEIP1559ScriptArtifact(string memory path)
365
        internal
366
        view
367
        virtual
368
        returns (EIP1559ScriptArtifact memory)
369
    {
370
        string memory data = vm.readFile(path);
371
        bytes memory parsedData = vm.parseJson(data);
372
        RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
373
        EIP1559ScriptArtifact memory artifact;
374
        artifact.libraries = rawArtifact.libraries;
375
        artifact.path = rawArtifact.path;
376
        artifact.timestamp = rawArtifact.timestamp;
377
        artifact.pending = rawArtifact.pending;
378
        artifact.txReturns = rawArtifact.txReturns;
379
        artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
380
        artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
381
        return artifact;
382
    }
383
384
    function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
385
        Tx1559[] memory txs = new Tx1559[](rawTxs.length);
386
        for (uint256 i; i < rawTxs.length; i++) {
387
            txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
388
        }
389
        return txs;
390
    }
391
392
    function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
393
        Tx1559 memory transaction;
394
        transaction.arguments = rawTx.arguments;
395
        transaction.contractName = rawTx.contractName;
396
        transaction.functionSig = rawTx.functionSig;
397
        transaction.hash = rawTx.hash;
398
        transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
399
        transaction.opcode = rawTx.opcode;
400
        return transaction;
401
    }
402
403
    function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
404
        internal
405
        pure
406
        virtual
407
        returns (Tx1559Detail memory)
408
    {
409
        Tx1559Detail memory txDetail;
410
        txDetail.data = rawDetail.data;
411
        txDetail.from = rawDetail.from;
412
        txDetail.to = rawDetail.to;
413
        txDetail.nonce = _bytesToUint(rawDetail.nonce);
414
        txDetail.txType = _bytesToUint(rawDetail.txType);
415
        txDetail.value = _bytesToUint(rawDetail.value);
416
        txDetail.gas = _bytesToUint(rawDetail.gas);
417
        txDetail.accessList = rawDetail.accessList;
418
        return txDetail;
419
    }
420
421
    function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
422
        string memory deployData = vm.readFile(path);
423
        bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions");
424
        RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
425
        return rawToConvertedEIPTx1559s(rawTxs);
426
    }
427
428
    function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
429
        string memory deployData = vm.readFile(path);
430
        string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
431
        bytes memory parsedDeployData = vm.parseJson(deployData, key);
432
        RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
433
        return rawToConvertedEIPTx1559(rawTx);
434
    }
435
436
    // Analogous to readTransactions, but for receipts.
437
    function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
438
        string memory deployData = vm.readFile(path);
439
        bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
440
        RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
441
        return rawToConvertedReceipts(rawReceipts);
442
    }
443
444
    function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
445
        string memory deployData = vm.readFile(path);
446
        string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
447
        bytes memory parsedDeployData = vm.parseJson(deployData, key);
448
        RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
449
        return rawToConvertedReceipt(rawReceipt);
450
    }
451
452
    function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
453
        Receipt[] memory receipts = new Receipt[](rawReceipts.length);
454
        for (uint256 i; i < rawReceipts.length; i++) {
455
            receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
456
        }
457
        return receipts;
458
    }
459
460
    function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
461
        Receipt memory receipt;
462
        receipt.blockHash = rawReceipt.blockHash;
463
        receipt.to = rawReceipt.to;
464
        receipt.from = rawReceipt.from;
465
        receipt.contractAddress = rawReceipt.contractAddress;
466
        receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
467
        receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
468
        receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
469
        receipt.status = _bytesToUint(rawReceipt.status);
470
        receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
471
        receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
472
        receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
473
        receipt.logsBloom = rawReceipt.logsBloom;
474
        receipt.transactionHash = rawReceipt.transactionHash;
475
        return receipt;
476
    }
477
478
    function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
479
        internal
480
        pure
481
        virtual
482
        returns (ReceiptLog[] memory)
483
    {
484
        ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
485
        for (uint256 i; i < rawLogs.length; i++) {
486
            logs[i].logAddress = rawLogs[i].logAddress;
487
            logs[i].blockHash = rawLogs[i].blockHash;
488
            logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
489
            logs[i].data = rawLogs[i].data;
490
            logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
491
            logs[i].topics = rawLogs[i].topics;
492
            logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
493
            logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
494
            logs[i].removed = rawLogs[i].removed;
495
        }
496
        return logs;
497
    }
498
499
    // Deploy a contract by fetching the contract bytecode from
500
    // the artifacts directory
501
    // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
502
    function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
503
        bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
504
        /// @solidity memory-safe-assembly
505
        assembly {
506
            addr := create(0, add(bytecode, 0x20), mload(bytecode))
507
        }
508
509
        require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
510
    }
511
512
    function deployCode(string memory what) internal virtual returns (address addr) {
513
        bytes memory bytecode = vm.getCode(what);
514
        /// @solidity memory-safe-assembly
515
        assembly {
516
            addr := create(0, add(bytecode, 0x20), mload(bytecode))
517
        }
518
519
        require(addr != address(0), "StdCheats deployCode(string): Deployment failed.");
520
    }
521
522
    /// @dev deploy contract with value on construction
523
    function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
524
        bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
525
        /// @solidity memory-safe-assembly
526
        assembly {
527
            addr := create(val, add(bytecode, 0x20), mload(bytecode))
528
        }
529
530
        require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
531
    }
532
533
    function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
534
        bytes memory bytecode = vm.getCode(what);
535
        /// @solidity memory-safe-assembly
536
        assembly {
537
            addr := create(val, add(bytecode, 0x20), mload(bytecode))
538
        }
539
540
        require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
541
    }
542
543
    // creates a labeled address and the corresponding private key
544
    function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
545
        privateKey = uint256(keccak256(abi.encodePacked(name)));
546
        addr = vm.addr(privateKey);
547
        vm.label(addr, name);
548
    }
549
550
    // creates a labeled address
551
    function makeAddr(string memory name) internal virtual returns (address addr) {
552
        (addr,) = makeAddrAndKey(name);
553
    }
554
555
    // Destroys an account immediately, sending the balance to beneficiary.
556
    // Destroying means: balance will be zero, code will be empty, and nonce will be 0
557
    // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce
558
    // only after tx ends, this will run immediately.
559
    function destroyAccount(address who, address beneficiary) internal virtual {
560
        uint256 currBalance = who.balance;
561
        vm.etch(who, abi.encode());
562
        vm.deal(who, 0);
563
        vm.resetNonce(who);
564
565
        uint256 beneficiaryBalance = beneficiary.balance;
566
        vm.deal(beneficiary, currBalance + beneficiaryBalance);
567
    }
568
569
    // creates a struct containing both a labeled address and the corresponding private key
570
    function makeAccount(string memory name) internal virtual returns (Account memory account) {
571
        (account.addr, account.key) = makeAddrAndKey(name);
572
    }
573
574
    function deriveRememberKey(string memory mnemonic, uint32 index)
575
        internal
576
        virtual
577
        returns (address who, uint256 privateKey)
578
    {
579
        privateKey = vm.deriveKey(mnemonic, index);
580
        who = vm.rememberKey(privateKey);
581
    }
582
583
    function _bytesToUint(bytes memory b) private pure returns (uint256) {
584
        require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
585
        return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
586
    }
587
588
    function isFork() internal view virtual returns (bool status) {
589
        try vm.activeFork() {
590
            status = true;
591
        } catch (bytes memory) {}
592
    }
593
594
    modifier skipWhenForking() {
595
        if (!isFork()) {
596
            _;
597
        }
598
    }
599
600
    modifier skipWhenNotForking() {
601
        if (isFork()) {
602
            _;
603
        }
604
    }
605
606
    modifier noGasMetering() {
607
        vm.pauseGasMetering();
608
        // To prevent turning gas monitoring back on with nested functions that use this modifier,
609
        // we check if gasMetering started in the off position. If it did, we don't want to turn
610
        // it back on until we exit the top level function that used the modifier
611
        //
612
        // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
613
        // funcA will have `gasStartedOff` as false, funcB will have it as true,
614
        // so we only turn metering back on at the end of the funcA
615
        bool gasStartedOff = gasMeteringOff;
616
        gasMeteringOff = true;
617
618
        _;
619
620
        // if gas metering was on when this modifier was called, turn it back on at the end
621
        if (!gasStartedOff) {
622
            gasMeteringOff = false;
623
            vm.resumeGasMetering();
624
        }
625
    }
626
627
    // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
628
    // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
629
    // can't simply access the chain ID in a normal view or pure function because the solc View Pure
630
    // Checker changed `chainid` from pure to view in 0.8.0.
631
    function _viewChainId() private view returns (uint256 chainId) {
632
        // Assembly required since `block.chainid` was introduced in 0.8.0.
633
        assembly {
634
            chainId := chainid()
635
        }
636
637
        address(this); // Silence warnings in older Solc versions.
638
    }
639
640
    function _pureChainId() private pure returns (uint256 chainId) {
641
        function() internal view returns (uint256) fnIn = _viewChainId;
642
        function() internal pure returns (uint256) pureChainId;
643
        assembly {
644
            pureChainId := fnIn
645
        }
646
        chainId = pureChainId();
647
    }
648
}
649
650
// Wrappers around cheatcodes to avoid footguns
651
abstract contract StdCheats is StdCheatsSafe {
652
    using stdStorage for StdStorage;
653
654
    StdStorage private stdstore;
655
    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
656
    address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
657
658
    // Skip forward or rewind time by the specified number of seconds
659
    function skip(uint256 time) internal virtual {
660
        vm.warp(vm.getBlockTimestamp() + time);
661
    }
662
663
    function rewind(uint256 time) internal virtual {
664
        vm.warp(vm.getBlockTimestamp() - time);
665
    }
666
667
    // Setup a prank from an address that has some ether
668
    function hoax(address msgSender) internal virtual {
669
        vm.deal(msgSender, 1 << 128);
670
        vm.prank(msgSender);
671
    }
672
673
    function hoax(address msgSender, uint256 give) internal virtual {
674
        vm.deal(msgSender, give);
675
        vm.prank(msgSender);
676
    }
677
678
    function hoax(address msgSender, address origin) internal virtual {
679
        vm.deal(msgSender, 1 << 128);
680
        vm.prank(msgSender, origin);
681
    }
682
683
    function hoax(address msgSender, address origin, uint256 give) internal virtual {
684
        vm.deal(msgSender, give);
685
        vm.prank(msgSender, origin);
686
    }
687
688
    // Start perpetual prank from an address that has some ether
689
    function startHoax(address msgSender) internal virtual {
690
        vm.deal(msgSender, 1 << 128);
691
        vm.startPrank(msgSender);
692
    }
693
694
    function startHoax(address msgSender, uint256 give) internal virtual {
695
        vm.deal(msgSender, give);
696
        vm.startPrank(msgSender);
697
    }
698
699
    // Start perpetual prank from an address that has some ether
700
    // tx.origin is set to the origin parameter
701
    function startHoax(address msgSender, address origin) internal virtual {
702
        vm.deal(msgSender, 1 << 128);
703
        vm.startPrank(msgSender, origin);
704
    }
705
706
    function startHoax(address msgSender, address origin, uint256 give) internal virtual {
707
        vm.deal(msgSender, give);
708
        vm.startPrank(msgSender, origin);
709
    }
710
711
    function changePrank(address msgSender) internal virtual {
712
        console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
713
        vm.stopPrank();
714
        vm.startPrank(msgSender);
715
    }
716
717
    function changePrank(address msgSender, address txOrigin) internal virtual {
718
        vm.stopPrank();
719
        vm.startPrank(msgSender, txOrigin);
720
    }
721
722
    // The same as Vm's `deal`
723
    // Use the alternative signature for ERC20 tokens
724
    function deal(address to, uint256 give) internal virtual {
725
        vm.deal(to, give);
726
    }
727
728
    // Set the balance of an account for any ERC20 token
729
    // Use the alternative signature to update `totalSupply`
730
    function deal(address token, address to, uint256 give) internal virtual {
731
        deal(token, to, give, false);
732
    }
733
734
    // Set the balance of an account for any ERC1155 token
735
    // Use the alternative signature to update `totalSupply`
736
    function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {
737
        dealERC1155(token, to, id, give, false);
738
    }
739
740
    function deal(address token, address to, uint256 give, bool adjust) internal virtual {
741
        // get current balance
742
        (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
743
        uint256 prevBal = abi.decode(balData, (uint256));
744
745
        // update balance
746
        stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
747
748
        // update total supply
749
        if (adjust) {
750
            (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd));
751
            uint256 totSup = abi.decode(totSupData, (uint256));
752
            if (give < prevBal) {
753
                totSup -= (prevBal - give);
754
            } else {
755
                totSup += (give - prevBal);
756
            }
757
            stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
758
        }
759
    }
760
761
    function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {
762
        // get current balance
763
        (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id));
764
        uint256 prevBal = abi.decode(balData, (uint256));
765
766
        // update balance
767
        stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);
768
769
        // update total supply
770
        if (adjust) {
771
            (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id));
772
            require(
773
                totSupData.length != 0,
774
                "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply."
775
            );
776
            uint256 totSup = abi.decode(totSupData, (uint256));
777
            if (give < prevBal) {
778
                totSup -= (prevBal - give);
779
            } else {
780
                totSup += (give - prevBal);
781
            }
782
            stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);
783
        }
784
    }
785
786
    function dealERC721(address token, address to, uint256 id) internal virtual {
787
        // check if token id is already minted and the actual owner.
788
        (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));
789
        require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted.");
790
791
        // get owner current balance
792
        (, bytes memory fromBalData) =
793
            token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));
794
        uint256 fromPrevBal = abi.decode(fromBalData, (uint256));
795
796
        // get new user current balance
797
        (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
798
        uint256 toPrevBal = abi.decode(toBalData, (uint256));
799
800
        // update balances
801
        stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);
802
        stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);
803
804
        // update owner
805
        stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);
806
    }
807
808
    function deployCodeTo(string memory what, address where) internal virtual {
809
        deployCodeTo(what, "", 0, where);
810
    }
811
812
    function deployCodeTo(string memory what, bytes memory args, address where) internal virtual {
813
        deployCodeTo(what, args, 0, where);
814
    }
815
816
    function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual {
817
        bytes memory creationCode = vm.getCode(what);
818
        vm.etch(where, abi.encodePacked(creationCode, args));
819
        (bool success, bytes memory runtimeBytecode) = where.call{value: value}("");
820
        require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
821
        vm.etch(where, runtimeBytecode);
822
    }
823
824
    // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.
825
    function console2_log_StdCheats(string memory p0) private view {
826
        (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
827
        status;
828
    }
829
}