arnaucube
arnaucube/poseidon-solidity-examplePublic Self-hosted repository
poseidon-solidity-example/lib/forge-std/src/StdCheats.sol
lib/forge-std/src/StdCheats.solRaw
  1// SPDX-License-Identifier: MIT
  2pragma solidity >=0.6.2 <0.9.0;
  3
  4pragma experimental ABIEncoderV2;
  5
  6import {StdStorage, stdStorage} from "./StdStorage.sol";
  7import {Vm} from "./Vm.sol";
  8
  9abstract contract StdCheatsSafe {
 10    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
 11
 12    bool private gasMeteringOff;
 13
 14    // Data structures to parse Transaction objects from the broadcast artifact
 15    // that conform to EIP1559. The Raw structs is what is parsed from the JSON
 16    // and then converted to the one that is used by the user for better UX.
 17
 18    struct RawTx1559 {
 19        string[] arguments;
 20        address contractAddress;
 21        string contractName;
 22        // json value name = function
 23        string functionSig;
 24        bytes32 hash;
 25        // json value name = tx
 26        RawTx1559Detail txDetail;
 27        // json value name = type
 28        string opcode;
 29    }
 30
 31    struct RawTx1559Detail {
 32        AccessList[] accessList;
 33        bytes data;
 34        address from;
 35        bytes gas;
 36        bytes nonce;
 37        address to;
 38        bytes txType;
 39        bytes value;
 40    }
 41
 42    struct Tx1559 {
 43        string[] arguments;
 44        address contractAddress;
 45        string contractName;
 46        string functionSig;
 47        bytes32 hash;
 48        Tx1559Detail txDetail;
 49        string opcode;
 50    }
 51
 52    struct Tx1559Detail {
 53        AccessList[] accessList;
 54        bytes data;
 55        address from;
 56        uint256 gas;
 57        uint256 nonce;
 58        address to;
 59        uint256 txType;
 60        uint256 value;
 61    }
 62
 63    // Data structures to parse Transaction objects from the broadcast artifact
 64    // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
 65    // and then converted to the one that is used by the user for better UX.
 66
 67    struct TxLegacy {
 68        string[] arguments;
 69        address contractAddress;
 70        string contractName;
 71        string functionSig;
 72        string hash;
 73        string opcode;
 74        TxDetailLegacy transaction;
 75    }
 76
 77    struct TxDetailLegacy {
 78        AccessList[] accessList;
 79        uint256 chainId;
 80        bytes data;
 81        address from;
 82        uint256 gas;
 83        uint256 gasPrice;
 84        bytes32 hash;
 85        uint256 nonce;
 86        bytes1 opcode;
 87        bytes32 r;
 88        bytes32 s;
 89        uint256 txType;
 90        address to;
 91        uint8 v;
 92        uint256 value;
 93    }
 94
 95    struct AccessList {
 96        address accessAddress;
 97        bytes32[] storageKeys;
 98    }
 99
100    // Data structures to parse Receipt objects from the broadcast artifact.
101    // The Raw structs is what is parsed from the JSON
102    // and then converted to the one that is used by the user for better UX.
103
104    struct RawReceipt {
105        bytes32 blockHash;
106        bytes blockNumber;
107        address contractAddress;
108        bytes cumulativeGasUsed;
109        bytes effectiveGasPrice;
110        address from;
111        bytes gasUsed;
112        RawReceiptLog[] logs;
113        bytes logsBloom;
114        bytes status;
115        address to;
116        bytes32 transactionHash;
117        bytes transactionIndex;
118    }
119
120    struct Receipt {
121        bytes32 blockHash;
122        uint256 blockNumber;
123        address contractAddress;
124        uint256 cumulativeGasUsed;
125        uint256 effectiveGasPrice;
126        address from;
127        uint256 gasUsed;
128        ReceiptLog[] logs;
129        bytes logsBloom;
130        uint256 status;
131        address to;
132        bytes32 transactionHash;
133        uint256 transactionIndex;
134    }
135
136    // Data structures to parse the entire broadcast artifact, assuming the
137    // transactions conform to EIP1559.
138
139    struct EIP1559ScriptArtifact {
140        string[] libraries;
141        string path;
142        string[] pending;
143        Receipt[] receipts;
144        uint256 timestamp;
145        Tx1559[] transactions;
146        TxReturn[] txReturns;
147    }
148
149    struct RawEIP1559ScriptArtifact {
150        string[] libraries;
151        string path;
152        string[] pending;
153        RawReceipt[] receipts;
154        TxReturn[] txReturns;
155        uint256 timestamp;
156        RawTx1559[] transactions;
157    }
158
159    struct RawReceiptLog {
160        // json value = address
161        address logAddress;
162        bytes32 blockHash;
163        bytes blockNumber;
164        bytes data;
165        bytes logIndex;
166        bool removed;
167        bytes32[] topics;
168        bytes32 transactionHash;
169        bytes transactionIndex;
170        bytes transactionLogIndex;
171    }
172
173    struct ReceiptLog {
174        // json value = address
175        address logAddress;
176        bytes32 blockHash;
177        uint256 blockNumber;
178        bytes data;
179        uint256 logIndex;
180        bytes32[] topics;
181        uint256 transactionIndex;
182        uint256 transactionLogIndex;
183        bool removed;
184    }
185
186    struct TxReturn {
187        string internalType;
188        string value;
189    }
190
191    function assumeNoPrecompiles(address addr) internal virtual {
192        // Assembly required since `block.chainid` was introduced in 0.8.0.
193        uint256 chainId;
194        assembly {
195            chainId := chainid()
196        }
197        assumeNoPrecompiles(addr, chainId);
198    }
199
200    function assumeNoPrecompiles(address addr, uint256 chainId) internal pure virtual {
201        // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific
202        // address), but the same rationale for excluding them applies so we include those too.
203
204        // These should be present on all EVM-compatible chains.
205        vm.assume(addr < address(0x1) || addr > address(0x9));
206
207        // forgefmt: disable-start
208        if (chainId == 10 || chainId == 420) {
209            // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
210            vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));
211        } else if (chainId == 42161 || chainId == 421613) {
212            // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
213            vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));
214        } else if (chainId == 43114 || chainId == 43113) {
215            // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
216            vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));
217            vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));
218            vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));
219        }
220        // forgefmt: disable-end
221    }
222
223    function readEIP1559ScriptArtifact(string memory path)
224        internal
225        view
226        virtual
227        returns (EIP1559ScriptArtifact memory)
228    {
229        string memory data = vm.readFile(path);
230        bytes memory parsedData = vm.parseJson(data);
231        RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
232        EIP1559ScriptArtifact memory artifact;
233        artifact.libraries = rawArtifact.libraries;
234        artifact.path = rawArtifact.path;
235        artifact.timestamp = rawArtifact.timestamp;
236        artifact.pending = rawArtifact.pending;
237        artifact.txReturns = rawArtifact.txReturns;
238        artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
239        artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
240        return artifact;
241    }
242
243    function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
244        Tx1559[] memory txs = new Tx1559[](rawTxs.length);
245        for (uint256 i; i < rawTxs.length; i++) {
246            txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
247        }
248        return txs;
249    }
250
251    function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
252        Tx1559 memory transaction;
253        transaction.arguments = rawTx.arguments;
254        transaction.contractName = rawTx.contractName;
255        transaction.functionSig = rawTx.functionSig;
256        transaction.hash = rawTx.hash;
257        transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
258        transaction.opcode = rawTx.opcode;
259        return transaction;
260    }
261
262    function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
263        internal
264        pure
265        virtual
266        returns (Tx1559Detail memory)
267    {
268        Tx1559Detail memory txDetail;
269        txDetail.data = rawDetail.data;
270        txDetail.from = rawDetail.from;
271        txDetail.to = rawDetail.to;
272        txDetail.nonce = _bytesToUint(rawDetail.nonce);
273        txDetail.txType = _bytesToUint(rawDetail.txType);
274        txDetail.value = _bytesToUint(rawDetail.value);
275        txDetail.gas = _bytesToUint(rawDetail.gas);
276        txDetail.accessList = rawDetail.accessList;
277        return txDetail;
278    }
279
280    function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
281        string memory deployData = vm.readFile(path);
282        bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions");
283        RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
284        return rawToConvertedEIPTx1559s(rawTxs);
285    }
286
287    function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
288        string memory deployData = vm.readFile(path);
289        string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
290        bytes memory parsedDeployData = vm.parseJson(deployData, key);
291        RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
292        return rawToConvertedEIPTx1559(rawTx);
293    }
294
295    // Analogous to readTransactions, but for receipts.
296    function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
297        string memory deployData = vm.readFile(path);
298        bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
299        RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
300        return rawToConvertedReceipts(rawReceipts);
301    }
302
303    function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
304        string memory deployData = vm.readFile(path);
305        string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
306        bytes memory parsedDeployData = vm.parseJson(deployData, key);
307        RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
308        return rawToConvertedReceipt(rawReceipt);
309    }
310
311    function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
312        Receipt[] memory receipts = new Receipt[](rawReceipts.length);
313        for (uint256 i; i < rawReceipts.length; i++) {
314            receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
315        }
316        return receipts;
317    }
318
319    function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
320        Receipt memory receipt;
321        receipt.blockHash = rawReceipt.blockHash;
322        receipt.to = rawReceipt.to;
323        receipt.from = rawReceipt.from;
324        receipt.contractAddress = rawReceipt.contractAddress;
325        receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
326        receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
327        receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
328        receipt.status = _bytesToUint(rawReceipt.status);
329        receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
330        receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
331        receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
332        receipt.logsBloom = rawReceipt.logsBloom;
333        receipt.transactionHash = rawReceipt.transactionHash;
334        return receipt;
335    }
336
337    function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
338        internal
339        pure
340        virtual
341        returns (ReceiptLog[] memory)
342    {
343        ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
344        for (uint256 i; i < rawLogs.length; i++) {
345            logs[i].logAddress = rawLogs[i].logAddress;
346            logs[i].blockHash = rawLogs[i].blockHash;
347            logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
348            logs[i].data = rawLogs[i].data;
349            logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
350            logs[i].topics = rawLogs[i].topics;
351            logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
352            logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
353            logs[i].removed = rawLogs[i].removed;
354        }
355        return logs;
356    }
357
358    // Deploy a contract by fetching the contract bytecode from
359    // the artifacts directory
360    // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
361    function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
362        bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
363        /// @solidity memory-safe-assembly
364        assembly {
365            addr := create(0, add(bytecode, 0x20), mload(bytecode))
366        }
367
368        require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
369    }
370
371    function deployCode(string memory what) internal virtual returns (address addr) {
372        bytes memory bytecode = vm.getCode(what);
373        /// @solidity memory-safe-assembly
374        assembly {
375            addr := create(0, add(bytecode, 0x20), mload(bytecode))
376        }
377
378        require(addr != address(0), "StdCheats deployCode(string): Deployment failed.");
379    }
380
381    /// @dev deploy contract with value on construction
382    function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
383        bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
384        /// @solidity memory-safe-assembly
385        assembly {
386            addr := create(val, add(bytecode, 0x20), mload(bytecode))
387        }
388
389        require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
390    }
391
392    function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
393        bytes memory bytecode = vm.getCode(what);
394        /// @solidity memory-safe-assembly
395        assembly {
396            addr := create(val, add(bytecode, 0x20), mload(bytecode))
397        }
398
399        require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
400    }
401
402    // creates a labeled address and the corresponding private key
403    function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
404        privateKey = uint256(keccak256(abi.encodePacked(name)));
405        addr = vm.addr(privateKey);
406        vm.label(addr, name);
407    }
408
409    // creates a labeled address
410    function makeAddr(string memory name) internal virtual returns (address addr) {
411        (addr,) = makeAddrAndKey(name);
412    }
413
414    function deriveRememberKey(string memory mnemonic, uint32 index)
415        internal
416        virtual
417        returns (address who, uint256 privateKey)
418    {
419        privateKey = vm.deriveKey(mnemonic, index);
420        who = vm.rememberKey(privateKey);
421    }
422
423    function _bytesToUint(bytes memory b) private pure returns (uint256) {
424        require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
425        return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
426    }
427
428    function isFork() internal view virtual returns (bool status) {
429        try vm.activeFork() {
430            status = true;
431        } catch (bytes memory) {}
432    }
433
434    modifier skipWhenForking() {
435        if (!isFork()) {
436            _;
437        }
438    }
439
440    modifier skipWhenNotForking() {
441        if (isFork()) {
442            _;
443        }
444    }
445
446    modifier noGasMetering() {
447        vm.pauseGasMetering();
448        // To prevent turning gas monitoring back on with nested functions that use this modifier,
449        // we check if gasMetering started in the off position. If it did, we don't want to turn
450        // it back on until we exit the top level function that used the modifier
451        //
452        // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
453        // funcA will have `gasStartedOff` as false, funcB will have it as true,
454        // so we only turn metering back on at the end of the funcA
455        bool gasStartedOff = gasMeteringOff;
456        gasMeteringOff = true;
457
458        _;
459
460        // if gas metering was on when this modifier was called, turn it back on at the end
461        if (!gasStartedOff) {
462            gasMeteringOff = false;
463            vm.resumeGasMetering();
464        }
465    }
466
467    // a cheat for fuzzing addresses that are payable only
468    // see https://github.com/foundry-rs/foundry/issues/3631
469    function assumePayable(address addr) internal virtual {
470        (bool success,) = payable(addr).call{value: 0}("");
471        vm.assume(success);
472    }
473}
474
475// Wrappers around cheatcodes to avoid footguns
476abstract contract StdCheats is StdCheatsSafe {
477    using stdStorage for StdStorage;
478
479    StdStorage private stdstore;
480    Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
481
482    // Skip forward or rewind time by the specified number of seconds
483    function skip(uint256 time) internal virtual {
484        vm.warp(block.timestamp + time);
485    }
486
487    function rewind(uint256 time) internal virtual {
488        vm.warp(block.timestamp - time);
489    }
490
491    // Setup a prank from an address that has some ether
492    function hoax(address who) internal virtual {
493        vm.deal(who, 1 << 128);
494        vm.prank(who);
495    }
496
497    function hoax(address who, uint256 give) internal virtual {
498        vm.deal(who, give);
499        vm.prank(who);
500    }
501
502    function hoax(address who, address origin) internal virtual {
503        vm.deal(who, 1 << 128);
504        vm.prank(who, origin);
505    }
506
507    function hoax(address who, address origin, uint256 give) internal virtual {
508        vm.deal(who, give);
509        vm.prank(who, origin);
510    }
511
512    // Start perpetual prank from an address that has some ether
513    function startHoax(address who) internal virtual {
514        vm.deal(who, 1 << 128);
515        vm.startPrank(who);
516    }
517
518    function startHoax(address who, uint256 give) internal virtual {
519        vm.deal(who, give);
520        vm.startPrank(who);
521    }
522
523    // Start perpetual prank from an address that has some ether
524    // tx.origin is set to the origin parameter
525    function startHoax(address who, address origin) internal virtual {
526        vm.deal(who, 1 << 128);
527        vm.startPrank(who, origin);
528    }
529
530    function startHoax(address who, address origin, uint256 give) internal virtual {
531        vm.deal(who, give);
532        vm.startPrank(who, origin);
533    }
534
535    function changePrank(address who) internal virtual {
536        vm.stopPrank();
537        vm.startPrank(who);
538    }
539
540    // The same as Vm's `deal`
541    // Use the alternative signature for ERC20 tokens
542    function deal(address to, uint256 give) internal virtual {
543        vm.deal(to, give);
544    }
545
546    // Set the balance of an account for any ERC20 token
547    // Use the alternative signature to update `totalSupply`
548    function deal(address token, address to, uint256 give) internal virtual {
549        deal(token, to, give, false);
550    }
551
552    function deal(address token, address to, uint256 give, bool adjust) internal virtual {
553        // get current balance
554        (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));
555        uint256 prevBal = abi.decode(balData, (uint256));
556
557        // update balance
558        stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
559
560        // update total supply
561        if (adjust) {
562            (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));
563            uint256 totSup = abi.decode(totSupData, (uint256));
564            if (give < prevBal) {
565                totSup -= (prevBal - give);
566            } else {
567                totSup += (give - prevBal);
568            }
569            stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
570        }
571    }
572}