arnaucube
arnaucube/poseidon-solidity-examplePublic Self-hosted repository
poseidon-solidity-example/lib/forge-std/src/StdUtils.sol
lib/forge-std/src/StdUtils.solRaw
  1// SPDX-License-Identifier: MIT
  2pragma solidity >=0.6.2 <0.9.0;
  3
  4pragma experimental ABIEncoderV2;
  5
  6import {IMulticall3} from "./interfaces/IMulticall3.sol";
  7// TODO Remove import.
  8import {VmSafe} from "./Vm.sol";
  9
 10abstract contract StdUtils {
 11    /*//////////////////////////////////////////////////////////////////////////
 12                                     CONSTANTS
 13    //////////////////////////////////////////////////////////////////////////*/
 14
 15    IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
 16    VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
 17    address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
 18    uint256 private constant INT256_MIN_ABS =
 19        57896044618658097711785492504343953926634992332820282019728792003956564819968;
 20    uint256 private constant UINT256_MAX =
 21        115792089237316195423570985008687907853269984665640564039457584007913129639935;
 22
 23    /*//////////////////////////////////////////////////////////////////////////
 24                                 INTERNAL FUNCTIONS
 25    //////////////////////////////////////////////////////////////////////////*/
 26
 27    function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
 28        require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
 29        // If x is between min and max, return x directly. This is to ensure that dictionary values
 30        // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188
 31        if (x >= min && x <= max) return x;
 32
 33        uint256 size = max - min + 1;
 34
 35        // If the value is 0, 1, 2, 3, warp that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.
 36        // This helps ensure coverage of the min/max values.
 37        if (x <= 3 && size > x) return min + x;
 38        if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);
 39
 40        // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
 41        if (x > max) {
 42            uint256 diff = x - max;
 43            uint256 rem = diff % size;
 44            if (rem == 0) return max;
 45            result = min + rem - 1;
 46        } else if (x < min) {
 47            uint256 diff = min - x;
 48            uint256 rem = diff % size;
 49            if (rem == 0) return min;
 50            result = max - rem + 1;
 51        }
 52    }
 53
 54    function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) {
 55        result = _bound(x, min, max);
 56        console2_log("Bound Result", result);
 57    }
 58
 59    function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) {
 60        require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
 61
 62        // Shifting all int256 values to uint256 to use _bound function. The range of two types are:
 63        // int256 : -(2**255) ~ (2**255 - 1)
 64        // uint256:     0     ~ (2**256 - 1)
 65        // So, add 2**255, INT256_MIN_ABS to the integer values.
 66        //
 67        // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.
 68        // So, use `~uint256(x) + 1` instead.
 69        uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);
 70        uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);
 71        uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);
 72
 73        uint256 y = _bound(_x, _min, _max);
 74
 75        // To move it back to int256 value, subtract INT256_MIN_ABS at here.
 76        result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);
 77        console2_log("Bound result", vm.toString(result));
 78    }
 79
 80    function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
 81        require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
 82        return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
 83    }
 84
 85    /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
 86    /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)
 87    function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
 88        // forgefmt: disable-start
 89        // 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.
 90        // A one byte integer uses its own value as its length prefix, there is no additional "0x80 + length" prefix that comes before it.
 91        if (nonce == 0x00)      return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));
 92        if (nonce <= 0x7f)      return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));
 93
 94        // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.
 95        if (nonce <= 2**8 - 1)  return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));
 96        if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));
 97        if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));
 98        // forgefmt: disable-end
 99
100        // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp
101        // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)
102        // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)
103        // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)
104        // We assume nobody can have a nonce large enough to require more than 32 bytes.
105        return addressFromLast20Bytes(
106            keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))
107        );
108    }
109
110    function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
111        internal
112        pure
113        virtual
114        returns (address)
115    {
116        return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash)));
117    }
118
119    // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.
120    function getTokenBalances(address token, address[] memory addresses)
121        internal
122        virtual
123        returns (uint256[] memory balances)
124    {
125        uint256 tokenCodeSize;
126        assembly {
127            tokenCodeSize := extcodesize(token)
128        }
129        require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
130
131        // ABI encode the aggregate call to Multicall3.
132        uint256 length = addresses.length;
133        IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);
134        for (uint256 i = 0; i < length; ++i) {
135            // 0x70a08231 = bytes4("balanceOf(address)"))
136            calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
137        }
138
139        // Make the aggregate call.
140        (, bytes[] memory returnData) = multicall.aggregate(calls);
141
142        // ABI decode the return data and return the balances.
143        balances = new uint256[](length);
144        for (uint256 i = 0; i < length; ++i) {
145            balances[i] = abi.decode(returnData[i], (uint256));
146        }
147    }
148
149    /*//////////////////////////////////////////////////////////////////////////
150                                 PRIVATE FUNCTIONS
151    //////////////////////////////////////////////////////////////////////////*/
152
153    function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
154        return address(uint160(uint256(bytesValue)));
155    }
156
157    // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.
158
159    function console2_log(string memory p0, uint256 p1) private view {
160        (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string,uint256)", p0, p1));
161        status;
162    }
163
164    function console2_log(string memory p0, string memory p1) private view {
165        (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string,string)", p0, p1));
166        status;
167    }
168}