contracts/lib/forge-std/src/StdUtils.sol 9.8 K raw
1
// SPDX-License-Identifier: MIT
2
pragma solidity >=0.6.2 <0.9.0;
3
4
pragma experimental ABIEncoderV2;
5
6
import {IMulticall3} from "./interfaces/IMulticall3.sol";
7
import {VmSafe} from "./Vm.sol";
8
9
abstract contract StdUtils {
10
    /*//////////////////////////////////////////////////////////////////////////
11
                                     CONSTANTS
12
    //////////////////////////////////////////////////////////////////////////*/
13
14
    IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
15
    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
16
    address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
17
    uint256 private constant INT256_MIN_ABS =
18
        57896044618658097711785492504343953926634992332820282019728792003956564819968;
19
    uint256 private constant SECP256K1_ORDER =
20
        115792089237316195423570985008687907852837564279074904382605163141518161494337;
21
    uint256 private constant UINT256_MAX =
22
        115792089237316195423570985008687907853269984665640564039457584007913129639935;
23
24
    // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
25
    address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
26
27
    /*//////////////////////////////////////////////////////////////////////////
28
                                 INTERNAL FUNCTIONS
29
    //////////////////////////////////////////////////////////////////////////*/
30
31
    function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
32
        require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
33
        // If x is between min and max, return x directly. This is to ensure that dictionary values
34
        // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188
35
        if (x >= min && x <= max) return x;
36
37
        uint256 size = max - min + 1;
38
39
        // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.
40
        // This helps ensure coverage of the min/max values.
41
        if (x <= 3 && size > x) return min + x;
42
        if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);
43
44
        // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
45
        if (x > max) {
46
            uint256 diff = x - max;
47
            uint256 rem = diff % size;
48
            if (rem == 0) return max;
49
            result = min + rem - 1;
50
        } else if (x < min) {
51
            uint256 diff = min - x;
52
            uint256 rem = diff % size;
53
            if (rem == 0) return min;
54
            result = max - rem + 1;
55
        }
56
    }
57
58
    function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
59
        result = _bound(x, min, max);
60
        console2_log_StdUtils("Bound result", result);
61
    }
62
63
    function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
64
        require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
65
66
        // Shifting all int256 values to uint256 to use _bound function. The range of two types are:
67
        // int256 : -(2**255) ~ (2**255 - 1)
68
        // uint256:     0     ~ (2**256 - 1)
69
        // So, add 2**255, INT256_MIN_ABS to the integer values.
70
        //
71
        // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.
72
        // So, use `~uint256(x) + 1` instead.
73
        uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);
74
        uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);
75
        uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);
76
77
        uint256 y = _bound(_x, _min, _max);
78
79
        // To move it back to int256 value, subtract INT256_MIN_ABS at here.
80
        result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);
81
    }
82
83
    function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
84
        result = _bound(x, min, max);
85
        console2_log_StdUtils("Bound result", vm.toString(result));
86
    }
87
88
    function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) {
89
        result = _bound(privateKey, 1, SECP256K1_ORDER - 1);
90
    }
91
92
    function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
93
        require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
94
        return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
95
    }
96
97
    /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
98
    /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)
99
    function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
100
        console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
101
        return vm.computeCreateAddress(deployer, nonce);
102
    }
103
104
    function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
105
        internal
106
        pure
107
        virtual
108
        returns (address)
109
    {
110
        console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
111
        return vm.computeCreate2Address(salt, initcodeHash, deployer);
112
    }
113
114
    /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer
115
    function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {
116
        console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
117
        return vm.computeCreate2Address(salt, initCodeHash);
118
    }
119
120
    /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments
121
    /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
122
    function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {
123
        return hashInitCode(creationCode, "");
124
    }
125
126
    /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2
127
    /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
128
    /// @param args the ABI-encoded arguments to the constructor of C
129
    function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {
130
        return keccak256(abi.encodePacked(creationCode, args));
131
    }
132
133
    // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.
134
    function getTokenBalances(address token, address[] memory addresses)
135
        internal
136
        virtual
137
        returns (uint256[] memory balances)
138
    {
139
        uint256 tokenCodeSize;
140
        assembly {
141
            tokenCodeSize := extcodesize(token)
142
        }
143
        require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
144
145
        // ABI encode the aggregate call to Multicall3.
146
        uint256 length = addresses.length;
147
        IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);
148
        for (uint256 i = 0; i < length; ++i) {
149
            // 0x70a08231 = bytes4("balanceOf(address)"))
150
            calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
151
        }
152
153
        // Make the aggregate call.
154
        (, bytes[] memory returnData) = multicall.aggregate(calls);
155
156
        // ABI decode the return data and return the balances.
157
        balances = new uint256[](length);
158
        for (uint256 i = 0; i < length; ++i) {
159
            balances[i] = abi.decode(returnData[i], (uint256));
160
        }
161
    }
162
163
    /*//////////////////////////////////////////////////////////////////////////
164
                                 PRIVATE FUNCTIONS
165
    //////////////////////////////////////////////////////////////////////////*/
166
167
    function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
168
        return address(uint160(uint256(bytesValue)));
169
    }
170
171
    // This section is used to prevent the compilation of console, which shortens the compilation time when console is
172
    // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid
173
    // any breaking changes to function signatures.
174
    function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn)
175
        internal
176
        pure
177
        returns (function(bytes memory) internal pure fnOut)
178
    {
179
        assembly {
180
            fnOut := fnIn
181
        }
182
    }
183
184
    function _sendLogPayload(bytes memory payload) internal pure {
185
        _castLogPayloadViewToPure(_sendLogPayloadView)(payload);
186
    }
187
188
    function _sendLogPayloadView(bytes memory payload) private view {
189
        uint256 payloadLength = payload.length;
190
        address consoleAddress = CONSOLE2_ADDRESS;
191
        /// @solidity memory-safe-assembly
192
        assembly {
193
            let payloadStart := add(payload, 32)
194
            let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
195
        }
196
    }
197
198
    function console2_log_StdUtils(string memory p0) private pure {
199
        _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
200
    }
201
202
    function console2_log_StdUtils(string memory p0, uint256 p1) private pure {
203
        _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
204
    }
205
206
    function console2_log_StdUtils(string memory p0, string memory p1) private pure {
207
        _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
208
    }
209
}