contracts/lib/forge-std/test/StdCheats.t.sol 22.2 K raw
1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.7.0 <0.9.0;
3
4
import {StdCheats} from "../src/StdCheats.sol";
5
import {Test} from "../src/Test.sol";
6
import {stdJson} from "../src/StdJson.sol";
7
import {stdToml} from "../src/StdToml.sol";
8
import {IERC20} from "../src/interfaces/IERC20.sol";
9
10
contract StdCheatsTest is Test {
11
    Bar test;
12
13
    using stdJson for string;
14
15
    function setUp() public {
16
        test = new Bar();
17
    }
18
19
    function test_Skip() public {
20
        vm.warp(100);
21
        skip(25);
22
        assertEq(block.timestamp, 125);
23
    }
24
25
    function test_Rewind() public {
26
        vm.warp(100);
27
        rewind(25);
28
        assertEq(block.timestamp, 75);
29
    }
30
31
    function test_Hoax() public {
32
        hoax(address(1337));
33
        test.bar{value: 100}(address(1337));
34
    }
35
36
    function test_HoaxOrigin() public {
37
        hoax(address(1337), address(1337));
38
        test.origin{value: 100}(address(1337));
39
    }
40
41
    function test_HoaxDifferentAddresses() public {
42
        hoax(address(1337), address(7331));
43
        test.origin{value: 100}(address(1337), address(7331));
44
    }
45
46
    function test_StartHoax() public {
47
        startHoax(address(1337));
48
        test.bar{value: 100}(address(1337));
49
        test.bar{value: 100}(address(1337));
50
        vm.stopPrank();
51
        test.bar(address(this));
52
    }
53
54
    function test_StartHoaxOrigin() public {
55
        startHoax(address(1337), address(1337));
56
        test.origin{value: 100}(address(1337));
57
        test.origin{value: 100}(address(1337));
58
        vm.stopPrank();
59
        test.bar(address(this));
60
    }
61
62
    function test_ChangePrankMsgSender() public {
63
        vm.startPrank(address(1337));
64
        test.bar(address(1337));
65
        changePrank(address(0xdead));
66
        test.bar(address(0xdead));
67
        changePrank(address(1337));
68
        test.bar(address(1337));
69
        vm.stopPrank();
70
    }
71
72
    function test_ChangePrankMsgSenderAndTxOrigin() public {
73
        vm.startPrank(address(1337), address(1338));
74
        test.origin(address(1337), address(1338));
75
        changePrank(address(0xdead), address(0xbeef));
76
        test.origin(address(0xdead), address(0xbeef));
77
        changePrank(address(1337), address(1338));
78
        test.origin(address(1337), address(1338));
79
        vm.stopPrank();
80
    }
81
82
    function test_MakeAccountEquivalence() public {
83
        Account memory account = makeAccount("1337");
84
        (address addr, uint256 key) = makeAddrAndKey("1337");
85
        assertEq(account.addr, addr);
86
        assertEq(account.key, key);
87
    }
88
89
    function test_MakeAddrEquivalence() public {
90
        (address addr,) = makeAddrAndKey("1337");
91
        assertEq(makeAddr("1337"), addr);
92
    }
93
94
    function test_MakeAddrSigning() public {
95
        (address addr, uint256 key) = makeAddrAndKey("1337");
96
        bytes32 hash = keccak256("some_message");
97
98
        (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash);
99
        assertEq(ecrecover(hash, v, r, s), addr);
100
    }
101
102
    function test_Deal() public {
103
        deal(address(this), 1 ether);
104
        assertEq(address(this).balance, 1 ether);
105
    }
106
107
    function test_DealToken() public {
108
        Bar barToken = new Bar();
109
        address bar = address(barToken);
110
        deal(bar, address(this), 10000e18);
111
        assertEq(barToken.balanceOf(address(this)), 10000e18);
112
    }
113
114
    function test_DealTokenAdjustTotalSupply() public {
115
        Bar barToken = new Bar();
116
        address bar = address(barToken);
117
        deal(bar, address(this), 10000e18, true);
118
        assertEq(barToken.balanceOf(address(this)), 10000e18);
119
        assertEq(barToken.totalSupply(), 20000e18);
120
        deal(bar, address(this), 0, true);
121
        assertEq(barToken.balanceOf(address(this)), 0);
122
        assertEq(barToken.totalSupply(), 10000e18);
123
    }
124
125
    function test_DealERC1155Token() public {
126
        BarERC1155 barToken = new BarERC1155();
127
        address bar = address(barToken);
128
        dealERC1155(bar, address(this), 0, 10000e18, false);
129
        assertEq(barToken.balanceOf(address(this), 0), 10000e18);
130
    }
131
132
    function test_DealERC1155TokenAdjustTotalSupply() public {
133
        BarERC1155 barToken = new BarERC1155();
134
        address bar = address(barToken);
135
        dealERC1155(bar, address(this), 0, 10000e18, true);
136
        assertEq(barToken.balanceOf(address(this), 0), 10000e18);
137
        assertEq(barToken.totalSupply(0), 20000e18);
138
        dealERC1155(bar, address(this), 0, 0, true);
139
        assertEq(barToken.balanceOf(address(this), 0), 0);
140
        assertEq(barToken.totalSupply(0), 10000e18);
141
    }
142
143
    function test_DealERC721Token() public {
144
        BarERC721 barToken = new BarERC721();
145
        address bar = address(barToken);
146
        dealERC721(bar, address(2), 1);
147
        assertEq(barToken.balanceOf(address(2)), 1);
148
        assertEq(barToken.balanceOf(address(1)), 0);
149
        dealERC721(bar, address(1), 2);
150
        assertEq(barToken.balanceOf(address(1)), 1);
151
        assertEq(barToken.balanceOf(bar), 1);
152
    }
153
154
    function test_DeployCode() public {
155
        address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""));
156
        assertEq(string(getCode(deployed)), string(getCode(address(test))));
157
    }
158
159
    function test_DestroyAccount() public {
160
        // deploy something to destroy it
161
        BarERC721 barToken = new BarERC721();
162
        address bar = address(barToken);
163
        vm.setNonce(bar, 10);
164
        deal(bar, 100);
165
166
        uint256 prevThisBalance = address(this).balance;
167
        uint256 size;
168
        assembly {
169
            size := extcodesize(bar)
170
        }
171
172
        assertGt(size, 0);
173
        assertEq(bar.balance, 100);
174
        assertEq(vm.getNonce(bar), 10);
175
176
        destroyAccount(bar, address(this));
177
        assembly {
178
            size := extcodesize(bar)
179
        }
180
        assertEq(address(this).balance, prevThisBalance + 100);
181
        assertEq(vm.getNonce(bar), 0);
182
        assertEq(size, 0);
183
        assertEq(bar.balance, 0);
184
    }
185
186
    function test_DeployCodeNoArgs() public {
187
        address deployed = deployCode("StdCheats.t.sol:Bar");
188
        assertEq(string(getCode(deployed)), string(getCode(address(test))));
189
    }
190
191
    function test_DeployCodeVal() public {
192
        address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""), 1 ether);
193
        assertEq(string(getCode(deployed)), string(getCode(address(test))));
194
        assertEq(deployed.balance, 1 ether);
195
    }
196
197
    function test_DeployCodeValNoArgs() public {
198
        address deployed = deployCode("StdCheats.t.sol:Bar", 1 ether);
199
        assertEq(string(getCode(deployed)), string(getCode(address(test))));
200
        assertEq(deployed.balance, 1 ether);
201
    }
202
203
    // We need this so we can call "this.deployCode" rather than "deployCode" directly
204
    function deployCodeHelper(string memory what) external {
205
        deployCode(what);
206
    }
207
208
    function test_RevertIf_DeployCodeFail() public {
209
        vm.expectRevert(bytes("StdCheats deployCode(string): Deployment failed."));
210
        this.deployCodeHelper("StdCheats.t.sol:RevertingContract");
211
    }
212
213
    function getCode(address who) internal view returns (bytes memory o_code) {
214
        /// @solidity memory-safe-assembly
215
        assembly {
216
            // retrieve the size of the code, this needs assembly
217
            let size := extcodesize(who)
218
            // allocate output byte array - this could also be done without assembly
219
            // by using o_code = new bytes(size)
220
            o_code := mload(0x40)
221
            // new "memory end" including padding
222
            mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
223
            // store length in memory
224
            mstore(o_code, size)
225
            // actually retrieve the code, this needs assembly
226
            extcodecopy(who, add(o_code, 0x20), 0, size)
227
        }
228
    }
229
230
    function test_DeriveRememberKey() public {
231
        string memory mnemonic = "test test test test test test test test test test test junk";
232
233
        (address deployer, uint256 privateKey) = deriveRememberKey(mnemonic, 0);
234
        assertEq(deployer, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
235
        assertEq(privateKey, 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80);
236
    }
237
238
    function test_BytesToUint() public pure {
239
        assertEq(3, bytesToUint_test(hex"03"));
240
        assertEq(2, bytesToUint_test(hex"02"));
241
        assertEq(255, bytesToUint_test(hex"ff"));
242
        assertEq(29625, bytesToUint_test(hex"73b9"));
243
    }
244
245
    function test_ParseJsonTxDetail() public view {
246
        string memory root = vm.projectRoot();
247
        string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
248
        string memory json = vm.readFile(path);
249
        bytes memory transactionDetails = json.parseRaw(".transactions[0].tx");
250
        RawTx1559Detail memory rawTxDetail = abi.decode(transactionDetails, (RawTx1559Detail));
251
        Tx1559Detail memory txDetail = rawToConvertedEIP1559Detail(rawTxDetail);
252
        assertEq(txDetail.from, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
253
        assertEq(txDetail.to, 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512);
254
        assertEq(
255
            txDetail.data,
256
            hex"23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004"
257
        );
258
        assertEq(txDetail.nonce, 3);
259
        assertEq(txDetail.txType, 2);
260
        assertEq(txDetail.gas, 29625);
261
        assertEq(txDetail.value, 0);
262
    }
263
264
    function test_ReadEIP1559Transaction() public view {
265
        string memory root = vm.projectRoot();
266
        string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
267
        uint256 index = 0;
268
        Tx1559 memory transaction = readTx1559(path, index);
269
        transaction;
270
    }
271
272
    function test_ReadEIP1559Transactions() public view {
273
        string memory root = vm.projectRoot();
274
        string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
275
        Tx1559[] memory transactions = readTx1559s(path);
276
        transactions;
277
    }
278
279
    function test_ReadReceipt() public view {
280
        string memory root = vm.projectRoot();
281
        string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
282
        uint256 index = 5;
283
        Receipt memory receipt = readReceipt(path, index);
284
        assertEq(
285
            receipt.logsBloom,
286
            hex"00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100"
287
        );
288
    }
289
290
    function test_ReadReceipts() public view {
291
        string memory root = vm.projectRoot();
292
        string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
293
        Receipt[] memory receipts = readReceipts(path);
294
        receipts;
295
    }
296
297
    function test_GasMeteringModifier() public {
298
        uint256 gas_start_normal = gasleft();
299
        addInLoop();
300
        uint256 gas_used_normal = gas_start_normal - gasleft();
301
302
        uint256 gas_start_single = gasleft();
303
        addInLoopNoGas();
304
        uint256 gas_used_single = gas_start_single - gasleft();
305
306
        uint256 gas_start_double = gasleft();
307
        addInLoopNoGasNoGas();
308
        uint256 gas_used_double = gas_start_double - gasleft();
309
310
        assertTrue(gas_used_double + gas_used_single < gas_used_normal);
311
    }
312
313
    function addInLoop() internal pure returns (uint256) {
314
        uint256 b;
315
        for (uint256 i; i < 10000; i++) {
316
            b += i;
317
        }
318
        return b;
319
    }
320
321
    function addInLoopNoGas() internal noGasMetering returns (uint256) {
322
        return addInLoop();
323
    }
324
325
    function addInLoopNoGasNoGas() internal noGasMetering returns (uint256) {
326
        return addInLoopNoGas();
327
    }
328
329
    function bytesToUint_test(bytes memory b) private pure returns (uint256) {
330
        uint256 number;
331
        for (uint256 i = 0; i < b.length; i++) {
332
            number = number + uint256(uint8(b[i])) * (2 ** (8 * (b.length - (i + 1))));
333
        }
334
        return number;
335
    }
336
337
    function testFuzz_AssumeAddressIsNot(address addr) external {
338
        // skip over Payable and NonPayable enums
339
        for (uint8 i = 2; i < uint8(type(AddressType).max); i++) {
340
            assumeAddressIsNot(addr, AddressType(i));
341
        }
342
        assertTrue(addr != address(0));
343
        assertTrue(addr < address(1) || addr > address(9));
344
        assertTrue(addr != address(vm) || addr != 0x000000000000000000636F6e736F6c652e6c6f67);
345
    }
346
347
    function test_AssumePayable() external {
348
        // We deploy a mock version so we can properly test the revert.
349
        StdCheatsMock stdCheatsMock = new StdCheatsMock();
350
351
        // all should revert since these addresses are not payable
352
353
        // VM address
354
        vm.expectRevert();
355
        stdCheatsMock.exposed_assumePayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
356
357
        // Console address
358
        vm.expectRevert();
359
        stdCheatsMock.exposed_assumePayable(0x000000000000000000636F6e736F6c652e6c6f67);
360
361
        // Create2Deployer
362
        vm.expectRevert();
363
        stdCheatsMock.exposed_assumePayable(0x4e59b44847b379578588920cA78FbF26c0B4956C);
364
365
        // all should pass since these addresses are payable
366
367
        // vitalik.eth
368
        stdCheatsMock.exposed_assumePayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045);
369
370
        // mock payable contract
371
        MockContractPayable cp = new MockContractPayable();
372
        stdCheatsMock.exposed_assumePayable(address(cp));
373
    }
374
375
    function test_AssumeNotPayable() external {
376
        // We deploy a mock version so we can properly test the revert.
377
        StdCheatsMock stdCheatsMock = new StdCheatsMock();
378
379
        // all should pass since these addresses are not payable
380
381
        // VM address
382
        stdCheatsMock.exposed_assumeNotPayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
383
384
        // Console address
385
        stdCheatsMock.exposed_assumeNotPayable(0x000000000000000000636F6e736F6c652e6c6f67);
386
387
        // Create2Deployer
388
        stdCheatsMock.exposed_assumeNotPayable(0x4e59b44847b379578588920cA78FbF26c0B4956C);
389
390
        // all should revert since these addresses are payable
391
392
        // vitalik.eth
393
        vm.expectRevert();
394
        stdCheatsMock.exposed_assumeNotPayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045);
395
396
        // mock payable contract
397
        MockContractPayable cp = new MockContractPayable();
398
        vm.expectRevert();
399
        stdCheatsMock.exposed_assumeNotPayable(address(cp));
400
    }
401
402
    function testFuzz_AssumeNotPrecompile(address addr) external {
403
        assumeNotPrecompile(addr, getChain("optimism_sepolia").chainId);
404
        assertTrue(
405
            addr < address(1) || (addr > address(9) && addr < address(0x4200000000000000000000000000000000000000))
406
                || addr > address(0x4200000000000000000000000000000000000800)
407
        );
408
    }
409
410
    function testFuzz_AssumeNotForgeAddress(address addr) external pure {
411
        assumeNotForgeAddress(addr);
412
        assertTrue(
413
            addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
414
                && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
415
        );
416
    }
417
418
    function test_RevertIf_CannotDeployCodeTo() external {
419
        vm.expectRevert("StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
420
        this._revertDeployCodeTo();
421
    }
422
423
    function _revertDeployCodeTo() external {
424
        deployCodeTo("StdCheats.t.sol:RevertingContract", address(0));
425
    }
426
427
    function test_DeployCodeTo() external {
428
        address arbitraryAddress = makeAddr("arbitraryAddress");
429
430
        deployCodeTo(
431
            "StdCheats.t.sol:MockContractWithConstructorArgs",
432
            abi.encode(uint256(6), true, bytes20(arbitraryAddress)),
433
            1 ether,
434
            arbitraryAddress
435
        );
436
437
        MockContractWithConstructorArgs ct = MockContractWithConstructorArgs(arbitraryAddress);
438
439
        assertEq(arbitraryAddress.balance, 1 ether);
440
        assertEq(ct.x(), 6);
441
        assertTrue(ct.y());
442
        assertEq(ct.z(), bytes20(arbitraryAddress));
443
    }
444
}
445
446
contract StdCheatsMock is StdCheats {
447
    function exposed_assumePayable(address addr) external {
448
        assumePayable(addr);
449
    }
450
451
    function exposed_assumeNotPayable(address addr) external {
452
        assumeNotPayable(addr);
453
    }
454
455
    // We deploy a mock version so we can properly test expected reverts.
456
    function exposed_assumeNotBlacklisted(address token, address addr) external view {
457
        return assumeNotBlacklisted(token, addr);
458
    }
459
}
460
461
contract StdCheatsForkTest is Test {
462
    address internal constant USDC_BLACKLISTED_USER = 0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD;
463
    address internal constant USDT_BLACKLISTED_USER = 0x8f8a8F4B54a2aAC7799d7bc81368aC27b852822A;
464
465
    MockUSDT public USDT;
466
    MockUSDC public USDC;
467
468
    function setUp() public {
469
        USDT = new MockUSDT();
470
        USDC = new MockUSDC();
471
472
        USDC.setBlacklisted(USDC_BLACKLISTED_USER, true);
473
        USDT.setBlacklisted(USDT_BLACKLISTED_USER, true);
474
    }
475
476
    function test_RevertIf_CannotAssumeNoBlacklisted_EOA() external {
477
        // We deploy a mock version so we can properly test the revert.
478
        StdCheatsMock stdCheatsMock = new StdCheatsMock();
479
        address eoa = vm.addr({privateKey: 1});
480
        vm.expectRevert("StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
481
        stdCheatsMock.exposed_assumeNotBlacklisted(eoa, address(0));
482
    }
483
484
    function testFuzz_AssumeNotBlacklisted_TokenWithoutBlacklist(address addr) external view {
485
        assumeNotBlacklisted(address(USDC), addr);
486
        assumeNotBlacklisted(address(USDT), addr);
487
        assertTrue(true);
488
    }
489
490
    function test_RevertIf_AssumeNoBlacklisted_USDC() external {
491
        // We deploy a mock version so we can properly test the revert.
492
        StdCheatsMock stdCheatsMock = new StdCheatsMock();
493
        vm.expectRevert();
494
        stdCheatsMock.exposed_assumeNotBlacklisted(address(USDC), USDC_BLACKLISTED_USER);
495
    }
496
497
    function testFuzz_AssumeNotBlacklisted_USDC(address addr) external view {
498
        assumeNotBlacklisted(address(USDC), addr);
499
        assertFalse(USDCLike(USDC).isBlacklisted(addr));
500
    }
501
502
    function test_RevertIf_AssumeNoBlacklisted_USDT() external {
503
        // We deploy a mock version so we can properly test the revert.
504
        StdCheatsMock stdCheatsMock = new StdCheatsMock();
505
        vm.expectRevert();
506
        stdCheatsMock.exposed_assumeNotBlacklisted(address(USDT), USDT_BLACKLISTED_USER);
507
    }
508
509
    function testFuzz_AssumeNotBlacklisted_USDT(address addr) external view {
510
        assumeNotBlacklisted(address(USDT), addr);
511
        assertFalse(USDTLike(USDT).isBlackListed(addr));
512
    }
513
}
514
515
/// @dev https://etherscan.io/token/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#readProxyContract
516
interface USDCLike {
517
    function isBlacklisted(address) external view returns (bool);
518
}
519
520
/// @dev https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7#readContract
521
interface USDTLike {
522
    function isBlackListed(address) external view returns (bool);
523
}
524
525
contract MockUSDT is USDTLike {
526
    mapping(address => bool) private blacklist;
527
528
    function isBlackListed(address addr) external view returns (bool) {
529
        return blacklist[addr];
530
    }
531
532
    function setBlacklisted(address addr, bool value) external {
533
        blacklist[addr] = value;
534
    }
535
}
536
537
contract MockUSDC is USDCLike {
538
    mapping(address => bool) private blacklist;
539
540
    function isBlacklisted(address addr) external view returns (bool) {
541
        return blacklist[addr];
542
    }
543
544
    function setBlacklisted(address addr, bool value) external {
545
        blacklist[addr] = value;
546
    }
547
}
548
549
contract Bar {
550
    constructor() payable {
551
        /// `DEAL` STDCHEAT
552
        totalSupply = 10000e18;
553
        balanceOf[address(this)] = totalSupply;
554
    }
555
556
    /// `HOAX` and `CHANGEPRANK` STDCHEATS
557
    function bar(address expectedSender) public payable {
558
        require(msg.sender == expectedSender, "!prank");
559
    }
560
561
    function origin(address expectedSender) public payable {
562
        require(msg.sender == expectedSender, "!prank");
563
        require(tx.origin == expectedSender, "!prank");
564
    }
565
566
    function origin(address expectedSender, address expectedOrigin) public payable {
567
        require(msg.sender == expectedSender, "!prank");
568
        require(tx.origin == expectedOrigin, "!prank");
569
    }
570
571
    /// `DEAL` STDCHEAT
572
    mapping(address => uint256) public balanceOf;
573
    uint256 public totalSupply;
574
}
575
576
contract BarERC1155 {
577
    constructor() payable {
578
        /// `DEALERC1155` STDCHEAT
579
        _totalSupply[0] = 10000e18;
580
        _balances[0][address(this)] = _totalSupply[0];
581
    }
582
583
    function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
584
        return _balances[id][account];
585
    }
586
587
    function totalSupply(uint256 id) public view virtual returns (uint256) {
588
        return _totalSupply[id];
589
    }
590
591
    /// `DEALERC1155` STDCHEAT
592
    mapping(uint256 => mapping(address => uint256)) private _balances;
593
    mapping(uint256 => uint256) private _totalSupply;
594
}
595
596
contract BarERC721 {
597
    constructor() payable {
598
        /// `DEALERC721` STDCHEAT
599
        _owners[1] = address(1);
600
        _balances[address(1)] = 1;
601
        _owners[2] = address(this);
602
        _owners[3] = address(this);
603
        _balances[address(this)] = 2;
604
    }
605
606
    function balanceOf(address owner) public view virtual returns (uint256) {
607
        return _balances[owner];
608
    }
609
610
    function ownerOf(uint256 tokenId) public view virtual returns (address) {
611
        address owner = _owners[tokenId];
612
        return owner;
613
    }
614
615
    mapping(uint256 => address) private _owners;
616
    mapping(address => uint256) private _balances;
617
}
618
619
contract RevertingContract {
620
    constructor() {
621
        revert();
622
    }
623
}
624
625
contract MockContractWithConstructorArgs {
626
    uint256 public immutable x;
627
    bool public y;
628
    bytes20 public z;
629
630
    constructor(uint256 _x, bool _y, bytes20 _z) payable {
631
        x = _x;
632
        y = _y;
633
        z = _z;
634
    }
635
}
636
637
contract MockContractPayable {
638
    receive() external payable {}
639
}