// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.9.0; pragma experimental ABIEncoderV2; import {IMulticall3} from "./interfaces/IMulticall3.sol"; import {VmSafe} from "./Vm.sol"; abstract contract StdUtils { /*////////////////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////////////////*/ IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; uint256 private constant INT256_MIN_ABS = 57896044618658097711785492504343953926634992332820282019728792003956564819968; uint256 private constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; /*////////////////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); // If x is between min and max, return x directly. This is to ensure that dictionary values // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 if (x >= min && x <= max) return x; uint256 size = max - min + 1; // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. // This helps ensure coverage of the min/max values. if (x <= 3 && size > x) return min + x; if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. if (x > max) { uint256 diff = x - max; uint256 rem = diff % size; if (rem == 0) return max; result = min + rem - 1; } else if (x < min) { uint256 diff = min - x; uint256 rem = diff % size; if (rem == 0) return min; result = max - rem + 1; } } function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) { result = _bound(x, min, max); console2_log("Bound Result", result); } function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); // Shifting all int256 values to uint256 to use _bound function. The range of two types are: // int256 : -(2**255) ~ (2**255 - 1) // uint256: 0 ~ (2**256 - 1) // So, add 2**255, INT256_MIN_ABS to the integer values. // // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. // So, use `~uint256(x) + 1` instead. uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); uint256 y = _bound(_x, _min, _max); // To move it back to int256 value, subtract INT256_MIN_ABS at here. result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); } function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) { result = _bound(x, min, max); console2_log("Bound result", vm.toString(result)); } function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); } /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { // forgefmt: disable-start // The integer zero is treated as an empty byte string, and as a result it only has a length prefix, 0x80, computed via 0x80 + 0. // A one byte integer uses its own value as its length prefix, there is no additional "0x80 + length" prefix that comes before it. if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))); if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))); // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length. if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce)))); if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce)))); if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce)))); // forgefmt: disable-end // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce) // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex) // We assume nobody can have a nonce large enough to require more than 32 bytes. return addressFromLast20Bytes( keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))) ); } function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) internal pure virtual returns (address) { return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash))); } /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { return computeCreate2Address(salt, initCodeHash, CREATE2_FACTORY); } /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { return hashInitCode(creationCode, ""); } /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode /// @param args the ABI-encoded arguments to the constructor of C function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { return keccak256(abi.encodePacked(creationCode, args)); } // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. function getTokenBalances(address token, address[] memory addresses) internal virtual returns (uint256[] memory balances) { uint256 tokenCodeSize; assembly { tokenCodeSize := extcodesize(token) } require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); // ABI encode the aggregate call to Multicall3. uint256 length = addresses.length; IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); for (uint256 i = 0; i < length; ++i) { // 0x70a08231 = bytes4("balanceOf(address)")) calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); } // Make the aggregate call. (, bytes[] memory returnData) = multicall.aggregate(calls); // ABI decode the return data and return the balances. balances = new uint256[](length); for (uint256 i = 0; i < length; ++i) { balances[i] = abi.decode(returnData[i], (uint256)); } } /*////////////////////////////////////////////////////////////////////////// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { return address(uint160(uint256(bytesValue))); } // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere. function console2_log(string memory p0, uint256 p1) private view { (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string,uint256)", p0, p1)); status; } function console2_log(string memory p0, string memory p1) private view { (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string,string)", p0, p1)); status; } }