From 20122a444d3822c046ec764e2427229f2eaeb971 Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 12 May 2022 14:48:06 -0700 Subject: [PATCH 01/44] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Fix=20startMeasuring?= =?UTF-8?q?Gas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/DSTestPlus.t.sol | 5 +++++ src/test/utils/DSTestPlus.sol | 11 +++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/test/DSTestPlus.t.sol b/src/test/DSTestPlus.t.sol index 8487f84c..3b49da23 100644 --- a/src/test/DSTestPlus.t.sol +++ b/src/test/DSTestPlus.t.sol @@ -69,4 +69,9 @@ contract DSTestPlusTest is DSTestPlus { assertGt(uint256(scratchSpace1), 0); assertGt(uint256(scratchSpace2), 0); } + + function testMeasuringGas() public { + startMeasuringGas(); + stopMeasuringGas(); + } } diff --git a/src/test/utils/DSTestPlus.sol b/src/test/utils/DSTestPlus.sol index bb1772d4..afd03f73 100644 --- a/src/test/utils/DSTestPlus.sol +++ b/src/test/utils/DSTestPlus.sol @@ -12,8 +12,7 @@ contract DSTestPlus is DSTest { address internal constant DEAD_ADDRESS = 0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF; - string private checkpointLabel; - uint256 private checkpointGasLeft = 1; // Start the slot warm. + uint256 private checkpointGasLeft; modifier brutalizeMemory(bytes memory brutalizeWith) { /// @solidity memory-safe-assembly @@ -48,8 +47,8 @@ contract DSTestPlus is DSTest { _; } - function startMeasuringGas(string memory label) internal virtual { - checkpointLabel = label; + function startMeasuringGas() internal virtual { + checkpointGasLeft = 1; // Start the slot warm. checkpointGasLeft = gasleft(); } @@ -57,10 +56,10 @@ contract DSTestPlus is DSTest { function stopMeasuringGas() internal virtual { uint256 checkpointGasLeft2 = gasleft(); - // Subtract 100 to account for the warm SLOAD in startMeasuringGas. + // Subtract 100 to account for the warm SSTORE in startMeasuringGas. uint256 gasDelta = checkpointGasLeft - checkpointGasLeft2 - 100; - emit log_named_uint(string(abi.encodePacked(checkpointLabel, " Gas")), gasDelta); + emit log_named_uint("Gas Used", gasDelta); } function fail(string memory err) internal virtual { From f3749feb9f8b709da7c4954f089252a81706493d Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 12 May 2022 14:48:12 -0700 Subject: [PATCH 02/44] Update .gas-snapshot --- .gas-snapshot | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 778ed7ab..e50cf40b 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -21,6 +21,7 @@ CREATE3Test:testFailDoubleDeploySameBytecode() (gas: 9079256848778906218) DSTestPlusTest:testBound() (gas: 14208) DSTestPlusTest:testBrutalizeMemory() (gas: 823) DSTestPlusTest:testFailBoundMinBiggerThanMax() (gas: 309) +DSTestPlusTest:testMeasuringGas() (gas: 24622) DSTestPlusTest:testRelApproxEqBothZeroesPasses() (gas: 413) ERC1155Test:testApproveAll() (gas: 31009) ERC1155Test:testBatchBalanceOf() (gas: 157631) @@ -74,19 +75,19 @@ ERC20Test:testMint() (gas: 53746) ERC20Test:testPermit() (gas: 63193) ERC20Test:testTransfer() (gas: 60272) ERC20Test:testTransferFrom() (gas: 83777) -ERC4626Test:testFailDepositWithNoApproval() (gas: 13351) -ERC4626Test:testFailDepositWithNotEnoughApproval() (gas: 86987) -ERC4626Test:testFailDepositZero() (gas: 7774) -ERC4626Test:testFailMintWithNoApproval() (gas: 13296) -ERC4626Test:testFailRedeemWithNoShareAmount() (gas: 32339) -ERC4626Test:testFailRedeemWithNotEnoughShareAmount() (gas: 203632) -ERC4626Test:testFailRedeemZero() (gas: 7961) -ERC4626Test:testFailWithdrawWithNoUnderlyingAmount() (gas: 32292) -ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203615) -ERC4626Test:testMintZero() (gas: 54598) -ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411940) -ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286247) -ERC4626Test:testWithdrawZero() (gas: 52465) +ERC4626Test:testFailDepositWithNoApproval() (gas: 13345) +ERC4626Test:testFailDepositWithNotEnoughApproval() (gas: 86963) +ERC4626Test:testFailDepositZero() (gas: 7768) +ERC4626Test:testFailMintWithNoApproval() (gas: 13290) +ERC4626Test:testFailRedeemWithNoShareAmount() (gas: 32333) +ERC4626Test:testFailRedeemWithNotEnoughShareAmount() (gas: 203605) +ERC4626Test:testFailRedeemZero() (gas: 7955) +ERC4626Test:testFailWithdrawWithNoUnderlyingAmount() (gas: 32286) +ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203588) +ERC4626Test:testMintZero() (gas: 54526) +ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411114) +ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286088) +ERC4626Test:testWithdrawZero() (gas: 52393) ERC721Test:testApprove() (gas: 78427) ERC721Test:testApproveAll() (gas: 31063) ERC721Test:testApproveBurn() (gas: 65550) From e1677c91454bf753ded221e739bb399ecf5e1e37 Mon Sep 17 00:00:00 2001 From: Gaussian-Process <103959739+Gaussian-Process@users.noreply.github.com> Date: Thu, 12 May 2022 15:05:18 -0700 Subject: [PATCH 03/44] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20A=20Cheaper=20Sqrt?= =?UTF-8?q?=20Function=20(#212)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 2 +- src/utils/FixedPointMathLib.sol | 84 ++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index e50cf40b..d0bb1145 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -143,7 +143,7 @@ FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 886) FixedPointMathLibTest:testMulWadUp() (gas: 959) FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 1002) FixedPointMathLibTest:testRPow() (gas: 2142) -FixedPointMathLibTest:testSqrt() (gas: 2537) +FixedPointMathLibTest:testSqrt() (gas: 2156) MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34292) MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80556) MultiRolesAuthorityTest:testCanCallWithCustomAuthority() (gas: 422681) diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index b4486907..2bee178a 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -165,43 +165,49 @@ library FixedPointMathLib { function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { - // Start off with z at 1. - z := 1 - - // Used below to help find a nearby power of 2. + // This segment is to get a reasonable initial estimate for the Babylonian method. + // If the initial estimate is bad, the number of correct bits increases ~linearly + // each iteration instead of ~quadratically. + // The idea is to get z*z*y within a small factor of x. + // More iterations here gets y in a tighter range. Currently, we will have + // y in [256, 256*2^16). We ensure y>= 256 so that the relative difference + // between y and y+1 is small. If x < 256 this is not possible, but those cases + // are easy enough to verify exhaustively. + z := 181 // The 'correct' value is 1, but this saves a multiply later let y := x - - // Find the lowest power of 2 that is at least sqrt(x). - if iszero(lt(y, 0x100000000000000000000000000000000)) { - y := shr(128, y) // Like dividing by 2 ** 128. - z := shl(64, z) // Like multiplying by 2 ** 64. - } - if iszero(lt(y, 0x10000000000000000)) { - y := shr(64, y) // Like dividing by 2 ** 64. - z := shl(32, z) // Like multiplying by 2 ** 32. - } - if iszero(lt(y, 0x100000000)) { - y := shr(32, y) // Like dividing by 2 ** 32. - z := shl(16, z) // Like multiplying by 2 ** 16. + // Note that we check y>= 2^(k + 8) but shift right by k bits each branch, + // this is to ensure that if x >= 256, then y >= 256. + if iszero(lt(y, 0x10000000000000000000000000000000000)) { + y := shr(128, y) + z := shl(64, z) } - if iszero(lt(y, 0x10000)) { - y := shr(16, y) // Like dividing by 2 ** 16. - z := shl(8, z) // Like multiplying by 2 ** 8. + if iszero(lt(y, 0x1000000000000000000)) { + y := shr(64, y) + z := shl(32, z) } - if iszero(lt(y, 0x100)) { - y := shr(8, y) // Like dividing by 2 ** 8. - z := shl(4, z) // Like multiplying by 2 ** 4. + if iszero(lt(y, 0x10000000000)) { + y := shr(32, y) + z := shl(16, z) } - if iszero(lt(y, 0x10)) { - y := shr(4, y) // Like dividing by 2 ** 4. - z := shl(2, z) // Like multiplying by 2 ** 2. + if iszero(lt(y, 0x1000000)) { + y := shr(16, y) + z := shl(8, z) } - if iszero(lt(y, 0x8)) { - // Equivalent to 2 ** z. - z := shl(1, z) - } - - // Shifting right by 1 is like dividing by 2. + // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), + // and either y >= 256, or x < 256. + // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. + // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. + + // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) + // is in the range (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s=1 + // and when s = 256 or 1/256. Since y is in [256, 256*2^16), let a = y/65536, so + // that a is in [1/256, 256). Then we can estimate sqrt(y) as + // sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18 + // There is no overflow risk here since y < 2^136 after the first branch above. + z := shr(18, mul(z, add(y, 65536))) // A multiply is saved from the initial z := 181 + + // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. + // Possibly with a quadratic/cubic polynomial above we could get 4-6. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) @@ -210,12 +216,14 @@ library FixedPointMathLib { z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) - // Compute a rounded down version of z. - let zRoundDown := div(x, z) - - // If zRoundDown is smaller, use it. - if lt(zRoundDown, z) { - z := zRoundDown + // See https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division. + // If x+1 is a perfect square, the Babylonian method cycles between + // floor(sqrt(x)) and ceil(sqrt(x)). This check ensures we return floor. + // Since this case is rare, we choose to save gas on the assignment and + // repeat division in the rare case. + // If you don't care whether floor or ceil is returned, you can skip this. + if lt(div(x, z), z) { + z := div(x, z) } } } From 0639fcbd73ad29528666b7ef7c2193418adfa394 Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 12 May 2022 15:05:31 -0700 Subject: [PATCH 04/44] =?UTF-8?q?=E2=9C=A8=20New=20libs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/LibBitmap.sol | 34 +++++++++++++++++++++++++++++++ src/utils/LibRLP.sol | 30 ++++++++++++++++++++++++++++ src/utils/LibString.sol | 44 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 src/utils/LibBitmap.sol create mode 100644 src/utils/LibRLP.sol create mode 100644 src/utils/LibString.sol diff --git a/src/utils/LibBitmap.sol b/src/utils/LibBitmap.sol new file mode 100644 index 00000000..a489037e --- /dev/null +++ b/src/utils/LibBitmap.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +/// @notice Efficient bitmap library for mapping integers to single bit booleans. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibBitmap.sol) +library LibBitmap { + struct Bitmap { + mapping(uint256 => uint256) map; + } + + function get(Bitmap storage bitmap, uint256 index) internal view returns (bool isSet) { + uint256 value = bitmap.map[index >> 8] & (1 << (index & 0xff)); + + assembly { + isSet := value // Assign isSet to whether the value is non zero. + } + } + + function set(Bitmap storage bitmap, uint256 index) internal { + bitmap.map[index >> 8] |= (1 << (index & 0xff)); + } + + function unset(Bitmap storage bitmap, uint256 index) internal { + bitmap.map[index >> 8] &= ~(1 << (index & 0xff)); + } + + function setTo( + Bitmap storage bitmap, + uint256 index, + bool shouldSet + ) internal { + shouldSet ? set(bitmap, index) : unset(bitmap, index); + } +} diff --git a/src/utils/LibRLP.sol b/src/utils/LibRLP.sol new file mode 100644 index 00000000..3fd9080c --- /dev/null +++ b/src/utils/LibRLP.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +import {Bytes32AddressLib} from "./Bytes32AddressLib.sol"; + +/// @notice Library for computing contract addresses from their deployer and nonce. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) +library LibRLP { + using Bytes32AddressLib for bytes32; + + // prettier-ignore + function computeAddress(address deployer, uint256 nonce) internal pure returns (address) { + // 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 keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))).fromLast20Bytes(); + if (nonce <= 0x7f) return keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))).fromLast20Bytes(); + + // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length. + if (nonce <= type(uint8).max) return keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))).fromLast20Bytes(); + if (nonce <= type(uint16).max) return keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))).fromLast20Bytes(); + if (nonce <= type(uint24).max) return keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))).fromLast20Bytes(); + + // 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 keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))).fromLast20Bytes(); + } +} diff --git a/src/utils/LibString.sol b/src/utils/LibString.sol new file mode 100644 index 00000000..6cb8aa2d --- /dev/null +++ b/src/utils/LibString.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +/// @notice Efficient library for creating string representations of integers. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibString.sol) +library LibString { + function toString(uint256 n) internal pure returns (string memory str) { + if (n == 0) return "0"; // Otherwise it'd output an empty string for 0. + + assembly { + let k := 78 // Start with the max length a uint256 string could be. + + // We'll store our string at the first chunk of free memory. + str := mload(0x40) + + // The length of our string will start off at the max of 78. + mstore(str, k) + + // Update the free memory pointer to prevent overriding our string. + // Add 128 to the str pointer instead of 78 because we want to maintain + // the Solidity convention of keeping the free memory pointer word aligned. + mstore(0x40, add(str, 128)) + + // We'll populate the string from right to left. + // prettier-ignore + for {} n {} { + // The ASCII digit offset for '0' is 48. + let char := add(48, mod(n, 10)) + + // Write the current character into str. + mstore(add(str, k), char) + + k := sub(k, 1) + n := div(n, 10) + } + + // Shift the pointer to the start of the string. + str := add(str, k) + + // Set the length of the string to the correct value. + mstore(str, sub(78, k)) + } + } +} From 02742406c777017026bd75d96e7483f1b86c09b0 Mon Sep 17 00:00:00 2001 From: brockelmore <31553173+brockelmore@users.noreply.github.com> Date: Thu, 12 May 2022 20:50:16 -0700 Subject: [PATCH 05/44] =?UTF-8?q?=E2=9C=85=20Change=20fuzz=20test=20naming?= =?UTF-8?q?=20convention=20(#224)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/Auth.t.sol | 24 +++++----- src/test/CREATE3.t.sol | 6 +-- src/test/DSTestPlus.t.sol | 4 +- src/test/ERC1155.t.sol | 76 +++++++++++++++--------------- src/test/ERC20.t.sol | 30 ++++++------ src/test/ERC4626.t.sol | 6 +-- src/test/ERC721.t.sol | 76 +++++++++++++++--------------- src/test/FixedPointMathLib.t.sol | 34 ++++++------- src/test/MultiRolesAuthority.t.sol | 18 +++---- src/test/RolesAuthority.t.sol | 10 ++-- src/test/SSTORE2.t.sol | 16 +++---- src/test/SafeCastLib.t.sol | 36 +++++++------- src/test/SafeTransferLib.t.sol | 64 ++++++++++++------------- src/test/WETH.t.sol | 6 +-- 14 files changed, 203 insertions(+), 203 deletions(-) diff --git a/src/test/Auth.t.sol b/src/test/Auth.t.sol index 19a6b846..5cb58d74 100644 --- a/src/test/Auth.t.sol +++ b/src/test/Auth.t.sol @@ -104,17 +104,17 @@ contract AuthTest is DSTestPlus { mockAuthChild.updateFlag(); } - function testSetOwnerAsOwner(address newOwner) public { + function testFuzzSetOwnerAsOwner(address newOwner) public { mockAuthChild.setOwner(newOwner); assertEq(mockAuthChild.owner(), newOwner); } - function testSetAuthorityAsOwner(Authority newAuthority) public { + function testFuzzSetAuthorityAsOwner(Authority newAuthority) public { mockAuthChild.setAuthority(newAuthority); assertEq(address(mockAuthChild.authority()), address(newAuthority)); } - function testSetOwnerWithPermissiveAuthority(address deadOwner, address newOwner) public { + function testFuzzSetOwnerWithPermissiveAuthority(address deadOwner, address newOwner) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setAuthority(new MockAuthority(true)); @@ -122,7 +122,7 @@ contract AuthTest is DSTestPlus { mockAuthChild.setOwner(newOwner); } - function testSetAuthorityWithPermissiveAuthority(address deadOwner, Authority newAuthority) public { + function testFuzzSetAuthorityWithPermissiveAuthority(address deadOwner, Authority newAuthority) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setAuthority(new MockAuthority(true)); @@ -130,7 +130,7 @@ contract AuthTest is DSTestPlus { mockAuthChild.setAuthority(newAuthority); } - function testCallFunctionWithPermissiveAuthority(address deadOwner) public { + function testFuzzCallFunctionWithPermissiveAuthority(address deadOwner) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setAuthority(new MockAuthority(true)); @@ -138,28 +138,28 @@ contract AuthTest is DSTestPlus { mockAuthChild.updateFlag(); } - function testFailSetOwnerAsNonOwner(address deadOwner, address newOwner) public { + function testFailFuzzSetOwnerAsNonOwner(address deadOwner, address newOwner) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setOwner(deadOwner); mockAuthChild.setOwner(newOwner); } - function testFailSetAuthorityAsNonOwner(address deadOwner, Authority newAuthority) public { + function testFailFuzzSetAuthorityAsNonOwner(address deadOwner, Authority newAuthority) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setOwner(deadOwner); mockAuthChild.setAuthority(newAuthority); } - function testFailCallFunctionAsNonOwner(address deadOwner) public { + function testFailFuzzCallFunctionAsNonOwner(address deadOwner) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setOwner(deadOwner); mockAuthChild.updateFlag(); } - function testFailSetOwnerWithRestrictiveAuthority(address deadOwner, address newOwner) public { + function testFailFuzzSetOwnerWithRestrictiveAuthority(address deadOwner, address newOwner) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setAuthority(new MockAuthority(false)); @@ -167,7 +167,7 @@ contract AuthTest is DSTestPlus { mockAuthChild.setOwner(newOwner); } - function testFailSetAuthorityWithRestrictiveAuthority(address deadOwner, Authority newAuthority) public { + function testFailFuzzSetAuthorityWithRestrictiveAuthority(address deadOwner, Authority newAuthority) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setAuthority(new MockAuthority(false)); @@ -175,7 +175,7 @@ contract AuthTest is DSTestPlus { mockAuthChild.setAuthority(newAuthority); } - function testFailCallFunctionWithRestrictiveAuthority(address deadOwner) public { + function testFailFuzzCallFunctionWithRestrictiveAuthority(address deadOwner) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setAuthority(new MockAuthority(false)); @@ -183,7 +183,7 @@ contract AuthTest is DSTestPlus { mockAuthChild.updateFlag(); } - function testFailSetOwnerAsOwnerWithOutOfOrderAuthority(address deadOwner) public { + function testFailFuzzSetOwnerAsOwnerWithOutOfOrderAuthority(address deadOwner) public { if (deadOwner == address(this)) deadOwner = address(0); mockAuthChild.setAuthority(new OutOfOrderAuthority()); diff --git a/src/test/CREATE3.t.sol b/src/test/CREATE3.t.sol index 8120632d..b09ee045 100644 --- a/src/test/CREATE3.t.sol +++ b/src/test/CREATE3.t.sol @@ -41,7 +41,7 @@ contract CREATE3Test is DSTestPlus { CREATE3.deploy(salt, type(MockAuthChild).creationCode, 0); } - function testDeployERC20( + function testFuzzDeployERC20( bytes32 salt, string calldata name, string calldata symbol, @@ -58,12 +58,12 @@ contract CREATE3Test is DSTestPlus { assertEq(deployed.decimals(), decimals); } - function testFailDoubleDeploySameBytecode(bytes32 salt, bytes calldata bytecode) public { + function testFailFuzzDoubleDeploySameBytecode(bytes32 salt, bytes calldata bytecode) public { CREATE3.deploy(salt, bytecode, 0); CREATE3.deploy(salt, bytecode, 0); } - function testFailDoubleDeployDifferentBytecode( + function testFailFuzzDoubleDeployDifferentBytecode( bytes32 salt, bytes calldata bytecode1, bytes calldata bytecode2 diff --git a/src/test/DSTestPlus.t.sol b/src/test/DSTestPlus.t.sol index 3b49da23..c6bf8894 100644 --- a/src/test/DSTestPlus.t.sol +++ b/src/test/DSTestPlus.t.sol @@ -22,7 +22,7 @@ contract DSTestPlusTest is DSTestPlus { assertRelApproxEq(0, 0, 0); } - function testBound( + function testFuzzBound( uint256 num, uint256 min, uint256 max @@ -35,7 +35,7 @@ contract DSTestPlusTest is DSTestPlus { assertLe(bounded, max); } - function testFailBoundMinBiggerThanMax( + function testFailFuzzBoundMinBiggerThanMax( uint256 num, uint256 min, uint256 max diff --git a/src/test/ERC1155.t.sol b/src/test/ERC1155.t.sol index c3d3deca..550146e1 100644 --- a/src/test/ERC1155.t.sol +++ b/src/test/ERC1155.t.sol @@ -830,7 +830,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.balanceOfBatch(tos, ids); } - function testMintToEOA( + function testFuzzMintToEOA( address to, uint256 id, uint256 amount, @@ -845,7 +845,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { assertEq(token.balanceOf(to, id), amount); } - function testMintToERC1155Recipient( + function testFuzzMintToERC1155Recipient( uint256 id, uint256 amount, bytes memory mintData @@ -862,7 +862,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { assertBytesEq(to.mintData(), mintData); } - function testBatchMintToEOA( + function testFuzzBatchMintToEOA( address to, uint256[] memory ids, uint256[] memory amounts, @@ -899,7 +899,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { } } - function testBatchMintToERC1155Recipient( + function testFuzzBatchMintToERC1155Recipient( uint256[] memory ids, uint256[] memory amounts, bytes memory mintData @@ -939,7 +939,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { } } - function testBurn( + function testFuzzBurn( address to, uint256 id, uint256 mintAmount, @@ -959,7 +959,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { assertEq(token.balanceOf(address(to), id), mintAmount - burnAmount); } - function testBatchBurn( + function testFuzzBatchBurn( address to, uint256[] memory ids, uint256[] memory mintAmounts, @@ -1000,13 +1000,13 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { } } - function testApproveAll(address to, bool approved) public { + function testFuzzApproveAll(address to, bool approved) public { token.setApprovalForAll(to, approved); assertBoolEq(token.isApprovedForAll(address(this), to), approved); } - function testSafeTransferFromToEOA( + function testFuzzSafeTransferFromToEOA( uint256 id, uint256 mintAmount, bytes memory mintData, @@ -1033,7 +1033,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { assertEq(token.balanceOf(from, id), mintAmount - transferAmount); } - function testSafeTransferFromToERC1155Recipient( + function testFuzzSafeTransferFromToERC1155Recipient( uint256 id, uint256 mintAmount, bytes memory mintData, @@ -1062,7 +1062,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { assertEq(token.balanceOf(from, id), mintAmount - transferAmount); } - function testSafeTransferFromSelf( + function testFuzzSafeTransferFromSelf( uint256 id, uint256 mintAmount, bytes memory mintData, @@ -1084,7 +1084,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { assertEq(token.balanceOf(address(this), id), mintAmount - transferAmount); } - function testSafeBatchTransferFromToEOA( + function testFuzzSafeBatchTransferFromToEOA( address to, uint256[] memory ids, uint256[] memory mintAmounts, @@ -1135,7 +1135,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { } } - function testSafeBatchTransferFromToERC1155Recipient( + function testFuzzSafeBatchTransferFromToERC1155Recipient( uint256[] memory ids, uint256[] memory mintAmounts, uint256[] memory transferAmounts, @@ -1190,7 +1190,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { } } - function testBatchBalanceOf( + function testFuzzBatchBalanceOf( address[] memory tos, uint256[] memory ids, uint256[] memory amounts, @@ -1224,7 +1224,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { } } - function testFailMintToZero( + function testFailFuzzMintToZero( uint256 id, uint256 amount, bytes memory data @@ -1232,7 +1232,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.mint(address(0), id, amount, data); } - function testFailMintToNonERC155Recipient( + function testFailFuzzMintToNonERC155Recipient( uint256 id, uint256 mintAmount, bytes memory mintData @@ -1240,7 +1240,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.mint(address(new NonERC1155Recipient()), id, mintAmount, mintData); } - function testFailMintToRevertingERC155Recipient( + function testFailFuzzMintToRevertingERC155Recipient( uint256 id, uint256 mintAmount, bytes memory mintData @@ -1248,7 +1248,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.mint(address(new RevertingERC1155Recipient()), id, mintAmount, mintData); } - function testFailMintToWrongReturnDataERC155Recipient( + function testFailFuzzMintToWrongReturnDataERC155Recipient( uint256 id, uint256 mintAmount, bytes memory mintData @@ -1256,7 +1256,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.mint(address(new RevertingERC1155Recipient()), id, mintAmount, mintData); } - function testFailBurnInsufficientBalance( + function testFailFuzzBurnInsufficientBalance( address to, uint256 id, uint256 mintAmount, @@ -1269,7 +1269,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.burn(to, id, burnAmount); } - function testFailSafeTransferFromInsufficientBalance( + function testFailFuzzSafeTransferFromInsufficientBalance( address to, uint256 id, uint256 mintAmount, @@ -1289,7 +1289,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.safeTransferFrom(from, to, id, transferAmount, transferData); } - function testFailSafeTransferFromSelfInsufficientBalance( + function testFailFuzzSafeTransferFromSelfInsufficientBalance( address to, uint256 id, uint256 mintAmount, @@ -1303,7 +1303,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.safeTransferFrom(address(this), to, id, transferAmount, transferData); } - function testFailSafeTransferFromToZero( + function testFailFuzzSafeTransferFromToZero( uint256 id, uint256 mintAmount, uint256 transferAmount, @@ -1316,7 +1316,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.safeTransferFrom(address(this), address(0), id, transferAmount, transferData); } - function testFailSafeTransferFromToNonERC155Recipient( + function testFailFuzzSafeTransferFromToNonERC155Recipient( uint256 id, uint256 mintAmount, uint256 transferAmount, @@ -1329,7 +1329,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.safeTransferFrom(address(this), address(new NonERC1155Recipient()), id, transferAmount, transferData); } - function testFailSafeTransferFromToRevertingERC1155Recipient( + function testFailFuzzSafeTransferFromToRevertingERC1155Recipient( uint256 id, uint256 mintAmount, uint256 transferAmount, @@ -1348,7 +1348,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { ); } - function testFailSafeTransferFromToWrongReturnDataERC1155Recipient( + function testFailFuzzSafeTransferFromToWrongReturnDataERC1155Recipient( uint256 id, uint256 mintAmount, uint256 transferAmount, @@ -1367,7 +1367,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { ); } - function testFailSafeBatchTransferInsufficientBalance( + function testFailFuzzSafeBatchTransferInsufficientBalance( address to, uint256[] memory ids, uint256[] memory mintAmounts, @@ -1408,7 +1408,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.safeBatchTransferFrom(from, to, normalizedIds, normalizedTransferAmounts, transferData); } - function testFailSafeBatchTransferFromToZero( + function testFailFuzzSafeBatchTransferFromToZero( uint256[] memory ids, uint256[] memory mintAmounts, uint256[] memory transferAmounts, @@ -1446,7 +1446,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.safeBatchTransferFrom(from, address(0), normalizedIds, normalizedTransferAmounts, transferData); } - function testFailSafeBatchTransferFromToNonERC1155Recipient( + function testFailFuzzSafeBatchTransferFromToNonERC1155Recipient( uint256[] memory ids, uint256[] memory mintAmounts, uint256[] memory transferAmounts, @@ -1490,7 +1490,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { ); } - function testFailSafeBatchTransferFromToRevertingERC1155Recipient( + function testFailFuzzSafeBatchTransferFromToRevertingERC1155Recipient( uint256[] memory ids, uint256[] memory mintAmounts, uint256[] memory transferAmounts, @@ -1534,7 +1534,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { ); } - function testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient( + function testFailFuzzSafeBatchTransferFromToWrongReturnDataERC1155Recipient( uint256[] memory ids, uint256[] memory mintAmounts, uint256[] memory transferAmounts, @@ -1578,7 +1578,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { ); } - function testFailSafeBatchTransferFromWithArrayLengthMismatch( + function testFailFuzzSafeBatchTransferFromWithArrayLengthMismatch( address to, uint256[] memory ids, uint256[] memory mintAmounts, @@ -1598,7 +1598,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.safeBatchTransferFrom(from, to, ids, transferAmounts, transferData); } - function testFailBatchMintToZero( + function testFailFuzzBatchMintToZero( uint256[] memory ids, uint256[] memory amounts, bytes memory mintData @@ -1624,7 +1624,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.batchMint(address(0), normalizedIds, normalizedAmounts, mintData); } - function testFailBatchMintToNonERC1155Recipient( + function testFailFuzzBatchMintToNonERC1155Recipient( uint256[] memory ids, uint256[] memory amounts, bytes memory mintData @@ -1652,7 +1652,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); } - function testFailBatchMintToRevertingERC1155Recipient( + function testFailFuzzBatchMintToRevertingERC1155Recipient( uint256[] memory ids, uint256[] memory amounts, bytes memory mintData @@ -1680,7 +1680,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); } - function testFailBatchMintToWrongReturnDataERC1155Recipient( + function testFailFuzzBatchMintToWrongReturnDataERC1155Recipient( uint256[] memory ids, uint256[] memory amounts, bytes memory mintData @@ -1708,7 +1708,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); } - function testFailBatchMintWithArrayMismatch( + function testFailFuzzBatchMintWithArrayMismatch( address to, uint256[] memory ids, uint256[] memory amounts, @@ -1719,7 +1719,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.batchMint(address(to), ids, amounts, mintData); } - function testFailBatchBurnInsufficientBalance( + function testFailFuzzBatchBurnInsufficientBalance( address to, uint256[] memory ids, uint256[] memory mintAmounts, @@ -1751,7 +1751,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.batchBurn(to, normalizedIds, normalizedBurnAmounts); } - function testFailBatchBurnWithArrayLengthMismatch( + function testFailFuzzBatchBurnWithArrayLengthMismatch( address to, uint256[] memory ids, uint256[] memory mintAmounts, @@ -1765,7 +1765,7 @@ contract ERC1155Test is DSTestPlus, ERC1155TokenReceiver { token.batchBurn(to, ids, burnAmounts); } - function testFailBalanceOfBatchWithArrayMismatch(address[] memory tos, uint256[] memory ids) public view { + function testFailFuzzBalanceOfBatchWithArrayMismatch(address[] memory tos, uint256[] memory ids) public view { if (tos.length == ids.length) revert(); token.balanceOfBatch(tos, ids); diff --git a/src/test/ERC20.t.sol b/src/test/ERC20.t.sol index 15c6f4ae..2d61c78c 100644 --- a/src/test/ERC20.t.sol +++ b/src/test/ERC20.t.sol @@ -208,7 +208,7 @@ contract ERC20Test is DSTestPlus { token.permit(owner, address(0xCAFE), 1e18, block.timestamp, v, r, s); } - function testMetadata( + function testFuzzMetadata( string calldata name, string calldata symbol, uint8 decimals @@ -219,14 +219,14 @@ contract ERC20Test is DSTestPlus { assertEq(tkn.decimals(), decimals); } - function testMint(address from, uint256 amount) public { + function testFuzzMint(address from, uint256 amount) public { token.mint(from, amount); assertEq(token.totalSupply(), amount); assertEq(token.balanceOf(from), amount); } - function testBurn( + function testFuzzBurn( address from, uint256 mintAmount, uint256 burnAmount @@ -240,13 +240,13 @@ contract ERC20Test is DSTestPlus { assertEq(token.balanceOf(from), mintAmount - burnAmount); } - function testApprove(address to, uint256 amount) public { + function testFuzzApprove(address to, uint256 amount) public { assertTrue(token.approve(to, amount)); assertEq(token.allowance(address(this), to), amount); } - function testTransfer(address from, uint256 amount) public { + function testFuzzTransfer(address from, uint256 amount) public { token.mint(address(this), amount); assertTrue(token.transfer(from, amount)); @@ -260,7 +260,7 @@ contract ERC20Test is DSTestPlus { } } - function testTransferFrom( + function testFuzzTransferFrom( address to, uint256 approval, uint256 amount @@ -288,7 +288,7 @@ contract ERC20Test is DSTestPlus { } } - function testPermit( + function testFuzzPermit( uint248 privKey, address to, uint256 amount, @@ -317,7 +317,7 @@ contract ERC20Test is DSTestPlus { assertEq(token.nonces(owner), 1); } - function testFailBurnInsufficientBalance( + function testFailFuzzBurnInsufficientBalance( address to, uint256 mintAmount, uint256 burnAmount @@ -328,7 +328,7 @@ contract ERC20Test is DSTestPlus { token.burn(to, burnAmount); } - function testFailTransferInsufficientBalance( + function testFailFuzzTransferInsufficientBalance( address to, uint256 mintAmount, uint256 sendAmount @@ -339,7 +339,7 @@ contract ERC20Test is DSTestPlus { token.transfer(to, sendAmount); } - function testFailTransferFromInsufficientAllowance( + function testFailFuzzTransferFromInsufficientAllowance( address to, uint256 approval, uint256 amount @@ -356,7 +356,7 @@ contract ERC20Test is DSTestPlus { token.transferFrom(from, to, amount); } - function testFailTransferFromInsufficientBalance( + function testFailFuzzTransferFromInsufficientBalance( address to, uint256 mintAmount, uint256 sendAmount @@ -373,7 +373,7 @@ contract ERC20Test is DSTestPlus { token.transferFrom(from, to, sendAmount); } - function testFailPermitBadNonce( + function testFailFuzzPermitBadNonce( uint256 privateKey, address to, uint256 amount, @@ -400,7 +400,7 @@ contract ERC20Test is DSTestPlus { token.permit(owner, to, amount, deadline, v, r, s); } - function testFailPermitBadDeadline( + function testFailFuzzPermitBadDeadline( uint256 privateKey, address to, uint256 amount, @@ -425,7 +425,7 @@ contract ERC20Test is DSTestPlus { token.permit(owner, to, amount, deadline + 1, v, r, s); } - function testFailPermitPastDeadline( + function testFailFuzzPermitPastDeadline( uint256 privateKey, address to, uint256 amount, @@ -450,7 +450,7 @@ contract ERC20Test is DSTestPlus { token.permit(owner, to, amount, deadline, v, r, s); } - function testFailPermitReplay( + function testFailFuzzPermitReplay( uint256 privateKey, address to, uint256 amount, diff --git a/src/test/ERC4626.t.sol b/src/test/ERC4626.t.sol index 56a17527..66aa8066 100644 --- a/src/test/ERC4626.t.sol +++ b/src/test/ERC4626.t.sol @@ -21,14 +21,14 @@ contract ERC4626Test is DSTestPlus { assertEq(vault.decimals(), 18); } - function testMetadata(string calldata name, string calldata symbol) public { + function testFuzzMetadata(string calldata name, string calldata symbol) public { MockERC4626 vlt = new MockERC4626(underlying, name, symbol); assertEq(vlt.name(), name); assertEq(vlt.symbol(), symbol); assertEq(address(vlt.asset()), address(underlying)); } - function testSingleDepositWithdraw(uint128 amount) public { + function testFuzzSingleDepositWithdraw(uint128 amount) public { if (amount == 0) amount = 1; uint256 aliceUnderlyingAmount = amount; @@ -69,7 +69,7 @@ contract ERC4626Test is DSTestPlus { assertEq(underlying.balanceOf(alice), alicePreDepositBal); } - function testSingleMintRedeem(uint128 amount) public { + function testFuzzSingleMintRedeem(uint128 amount) public { if (amount == 0) amount = 1; uint256 aliceShareAmount = amount; diff --git a/src/test/ERC721.t.sol b/src/test/ERC721.t.sol index 1f2b5098..45f8b9f4 100644 --- a/src/test/ERC721.t.sol +++ b/src/test/ERC721.t.sol @@ -368,14 +368,14 @@ contract ERC721Test is DSTestPlus { token.ownerOf(1337); } - function testMetadata(string memory name, string memory symbol) public { + function testFuzzMetadata(string memory name, string memory symbol) public { MockERC721 tkn = new MockERC721(name, symbol); assertEq(tkn.name(), name); assertEq(tkn.symbol(), symbol); } - function testMint(address to, uint256 id) public { + function testFuzzMint(address to, uint256 id) public { if (to == address(0)) to = address(0xBEEF); token.mint(to, id); @@ -384,7 +384,7 @@ contract ERC721Test is DSTestPlus { assertEq(token.ownerOf(id), to); } - function testBurn(address to, uint256 id) public { + function testFuzzBurn(address to, uint256 id) public { if (to == address(0)) to = address(0xBEEF); token.mint(to, id); @@ -396,7 +396,7 @@ contract ERC721Test is DSTestPlus { token.ownerOf(id); } - function testApprove(address to, uint256 id) public { + function testFuzzApprove(address to, uint256 id) public { if (to == address(0)) to = address(0xBEEF); token.mint(address(this), id); @@ -406,7 +406,7 @@ contract ERC721Test is DSTestPlus { assertEq(token.getApproved(id), to); } - function testApproveBurn(address to, uint256 id) public { + function testFuzzApproveBurn(address to, uint256 id) public { token.mint(address(this), id); token.approve(address(to), id); @@ -420,13 +420,13 @@ contract ERC721Test is DSTestPlus { token.ownerOf(id); } - function testApproveAll(address to, bool approved) public { + function testFuzzApproveAll(address to, bool approved) public { token.setApprovalForAll(to, approved); assertBoolEq(token.isApprovedForAll(address(this), to), approved); } - function testTransferFrom(uint256 id, address to) public { + function testFuzzTransferFrom(uint256 id, address to) public { address from = address(0xABCD); if (to == address(0) || to == from) to = address(0xBEEF); @@ -444,7 +444,7 @@ contract ERC721Test is DSTestPlus { assertEq(token.balanceOf(from), 0); } - function testTransferFromSelf(uint256 id, address to) public { + function testFuzzTransferFromSelf(uint256 id, address to) public { if (to == address(0) || to == address(this)) to = address(0xBEEF); token.mint(address(this), id); @@ -457,7 +457,7 @@ contract ERC721Test is DSTestPlus { assertEq(token.balanceOf(address(this)), 0); } - function testTransferFromApproveAll(uint256 id, address to) public { + function testFuzzTransferFromApproveAll(uint256 id, address to) public { address from = address(0xABCD); if (to == address(0) || to == from) to = address(0xBEEF); @@ -475,7 +475,7 @@ contract ERC721Test is DSTestPlus { assertEq(token.balanceOf(from), 0); } - function testSafeTransferFromToEOA(uint256 id, address to) public { + function testFuzzSafeTransferFromToEOA(uint256 id, address to) public { address from = address(0xABCD); if (to == address(0) || to == from) to = address(0xBEEF); @@ -495,7 +495,7 @@ contract ERC721Test is DSTestPlus { assertEq(token.balanceOf(from), 0); } - function testSafeTransferFromToERC721Recipient(uint256 id) public { + function testFuzzSafeTransferFromToERC721Recipient(uint256 id) public { address from = address(0xABCD); ERC721Recipient recipient = new ERC721Recipient(); @@ -518,7 +518,7 @@ contract ERC721Test is DSTestPlus { assertBytesEq(recipient.data(), ""); } - function testSafeTransferFromToERC721RecipientWithData(uint256 id, bytes calldata data) public { + function testFuzzSafeTransferFromToERC721RecipientWithData(uint256 id, bytes calldata data) public { address from = address(0xABCD); ERC721Recipient recipient = new ERC721Recipient(); @@ -540,7 +540,7 @@ contract ERC721Test is DSTestPlus { assertBytesEq(recipient.data(), data); } - function testSafeMintToEOA(uint256 id, address to) public { + function testFuzzSafeMintToEOA(uint256 id, address to) public { if (to == address(0)) to = address(0xBEEF); if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; @@ -551,7 +551,7 @@ contract ERC721Test is DSTestPlus { assertEq(token.balanceOf(address(to)), 1); } - function testSafeMintToERC721Recipient(uint256 id) public { + function testFuzzSafeMintToERC721Recipient(uint256 id) public { ERC721Recipient to = new ERC721Recipient(); token.safeMint(address(to), id); @@ -565,7 +565,7 @@ contract ERC721Test is DSTestPlus { assertBytesEq(to.data(), ""); } - function testSafeMintToERC721RecipientWithData(uint256 id, bytes calldata data) public { + function testFuzzSafeMintToERC721RecipientWithData(uint256 id, bytes calldata data) public { ERC721Recipient to = new ERC721Recipient(); token.safeMint(address(to), id, data); @@ -579,22 +579,22 @@ contract ERC721Test is DSTestPlus { assertBytesEq(to.data(), data); } - function testFailMintToZero(uint256 id) public { + function testFailFuzzMintToZero(uint256 id) public { token.mint(address(0), id); } - function testFailDoubleMint(uint256 id, address to) public { + function testFailFuzzDoubleMint(uint256 id, address to) public { if (to == address(0)) to = address(0xBEEF); token.mint(to, id); token.mint(to, id); } - function testFailBurnUnMinted(uint256 id) public { + function testFailFuzzBurnUnMinted(uint256 id) public { token.burn(id); } - function testFailDoubleBurn(uint256 id, address to) public { + function testFailFuzzDoubleBurn(uint256 id, address to) public { if (to == address(0)) to = address(0xBEEF); token.mint(to, id); @@ -603,11 +603,11 @@ contract ERC721Test is DSTestPlus { token.burn(id); } - function testFailApproveUnMinted(uint256 id, address to) public { + function testFailFuzzApproveUnMinted(uint256 id, address to) public { token.approve(to, id); } - function testFailApproveUnAuthorized( + function testFailFuzzApproveUnAuthorized( address owner, uint256 id, address to @@ -619,7 +619,7 @@ contract ERC721Test is DSTestPlus { token.approve(to, id); } - function testFailTransferFromUnOwned( + function testFailFuzzTransferFromUnOwned( address from, address to, uint256 id @@ -627,7 +627,7 @@ contract ERC721Test is DSTestPlus { token.transferFrom(from, to, id); } - function testFailTransferFromWrongFrom( + function testFailFuzzTransferFromWrongFrom( address owner, address from, address to, @@ -641,13 +641,13 @@ contract ERC721Test is DSTestPlus { token.transferFrom(from, to, id); } - function testFailTransferFromToZero(uint256 id) public { + function testFailFuzzTransferFromToZero(uint256 id) public { token.mint(address(this), id); token.transferFrom(address(this), address(0), id); } - function testFailTransferFromNotOwner( + function testFailFuzzTransferFromNotOwner( address from, address to, uint256 id @@ -659,37 +659,37 @@ contract ERC721Test is DSTestPlus { token.transferFrom(from, to, id); } - function testFailSafeTransferFromToNonERC721Recipient(uint256 id) public { + function testFailFuzzSafeTransferFromToNonERC721Recipient(uint256 id) public { token.mint(address(this), id); token.safeTransferFrom(address(this), address(new NonERC721Recipient()), id); } - function testFailSafeTransferFromToNonERC721RecipientWithData(uint256 id, bytes calldata data) public { + function testFailFuzzSafeTransferFromToNonERC721RecipientWithData(uint256 id, bytes calldata data) public { token.mint(address(this), id); token.safeTransferFrom(address(this), address(new NonERC721Recipient()), id, data); } - function testFailSafeTransferFromToRevertingERC721Recipient(uint256 id) public { + function testFailFuzzSafeTransferFromToRevertingERC721Recipient(uint256 id) public { token.mint(address(this), id); token.safeTransferFrom(address(this), address(new RevertingERC721Recipient()), id); } - function testFailSafeTransferFromToRevertingERC721RecipientWithData(uint256 id, bytes calldata data) public { + function testFailFuzzSafeTransferFromToRevertingERC721RecipientWithData(uint256 id, bytes calldata data) public { token.mint(address(this), id); token.safeTransferFrom(address(this), address(new RevertingERC721Recipient()), id, data); } - function testFailSafeTransferFromToERC721RecipientWithWrongReturnData(uint256 id) public { + function testFailFuzzSafeTransferFromToERC721RecipientWithWrongReturnData(uint256 id) public { token.mint(address(this), id); token.safeTransferFrom(address(this), address(new WrongReturnDataERC721Recipient()), id); } - function testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData(uint256 id, bytes calldata data) + function testFailFuzzSafeTransferFromToERC721RecipientWithWrongReturnDataWithData(uint256 id, bytes calldata data) public { token.mint(address(this), id); @@ -697,31 +697,31 @@ contract ERC721Test is DSTestPlus { token.safeTransferFrom(address(this), address(new WrongReturnDataERC721Recipient()), id, data); } - function testFailSafeMintToNonERC721Recipient(uint256 id) public { + function testFailFuzzSafeMintToNonERC721Recipient(uint256 id) public { token.safeMint(address(new NonERC721Recipient()), id); } - function testFailSafeMintToNonERC721RecipientWithData(uint256 id, bytes calldata data) public { + function testFailFuzzSafeMintToNonERC721RecipientWithData(uint256 id, bytes calldata data) public { token.safeMint(address(new NonERC721Recipient()), id, data); } - function testFailSafeMintToRevertingERC721Recipient(uint256 id) public { + function testFailFuzzSafeMintToRevertingERC721Recipient(uint256 id) public { token.safeMint(address(new RevertingERC721Recipient()), id); } - function testFailSafeMintToRevertingERC721RecipientWithData(uint256 id, bytes calldata data) public { + function testFailFuzzSafeMintToRevertingERC721RecipientWithData(uint256 id, bytes calldata data) public { token.safeMint(address(new RevertingERC721Recipient()), id, data); } - function testFailSafeMintToERC721RecipientWithWrongReturnData(uint256 id) public { + function testFailFuzzSafeMintToERC721RecipientWithWrongReturnData(uint256 id) public { token.safeMint(address(new WrongReturnDataERC721Recipient()), id); } - function testFailSafeMintToERC721RecipientWithWrongReturnDataWithData(uint256 id, bytes calldata data) public { + function testFailFuzzSafeMintToERC721RecipientWithWrongReturnDataWithData(uint256 id, bytes calldata data) public { token.safeMint(address(new WrongReturnDataERC721Recipient()), id, data); } - function testFailOwnerOfUnminted(uint256 id) public view { + function testFailFuzzOwnerOfUnminted(uint256 id) public view { token.ownerOf(id); } } diff --git a/src/test/FixedPointMathLib.t.sol b/src/test/FixedPointMathLib.t.sol index 6e259f7c..8dece878 100644 --- a/src/test/FixedPointMathLib.t.sol +++ b/src/test/FixedPointMathLib.t.sol @@ -123,7 +123,7 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.sqrt(32239684), 5678); } - function testMulWadDown(uint256 x, uint256 y) public { + function testFuzzMulWadDown(uint256 x, uint256 y) public { // Ignore cases where x * y overflows. unchecked { if (x != 0 && (x * y) / x != y) return; @@ -132,7 +132,7 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.mulWadDown(x, y), (x * y) / 1e18); } - function testFailMulWadDownOverflow(uint256 x, uint256 y) public pure { + function testFailFuzzMulWadDownOverflow(uint256 x, uint256 y) public pure { // Ignore cases where x * y does not overflow. unchecked { if ((x * y) / x == y) revert(); @@ -141,7 +141,7 @@ contract FixedPointMathLibTest is DSTestPlus { FixedPointMathLib.mulWadDown(x, y); } - function testMulWadUp(uint256 x, uint256 y) public { + function testFuzzMulWadUp(uint256 x, uint256 y) public { // Ignore cases where x * y overflows. unchecked { if (x != 0 && (x * y) / x != y) return; @@ -150,7 +150,7 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.mulWadUp(x, y), x * y == 0 ? 0 : (x * y - 1) / 1e18 + 1); } - function testFailMulWadUpOverflow(uint256 x, uint256 y) public pure { + function testFailFuzzMulWadUpOverflow(uint256 x, uint256 y) public pure { // Ignore cases where x * y does not overflow. unchecked { if ((x * y) / x == y) revert(); @@ -159,7 +159,7 @@ contract FixedPointMathLibTest is DSTestPlus { FixedPointMathLib.mulWadUp(x, y); } - function testDivWadDown(uint256 x, uint256 y) public { + function testFuzzDivWadDown(uint256 x, uint256 y) public { // Ignore cases where x * WAD overflows or y is 0. unchecked { if (y == 0 || (x != 0 && (x * 1e18) / 1e18 != x)) return; @@ -168,7 +168,7 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.divWadDown(x, y), (x * 1e18) / y); } - function testFailDivWadDownOverflow(uint256 x, uint256 y) public pure { + function testFailFuzzDivWadDownOverflow(uint256 x, uint256 y) public pure { // Ignore cases where x * WAD does not overflow or y is 0. unchecked { if (y == 0 || (x * 1e18) / 1e18 == x) revert(); @@ -177,11 +177,11 @@ contract FixedPointMathLibTest is DSTestPlus { FixedPointMathLib.divWadDown(x, y); } - function testFailDivWadDownZeroDenominator(uint256 x) public pure { + function testFailFuzzDivWadDownZeroDenominator(uint256 x) public pure { FixedPointMathLib.divWadDown(x, 0); } - function testDivWadUp(uint256 x, uint256 y) public { + function testFuzzDivWadUp(uint256 x, uint256 y) public { // Ignore cases where x * WAD overflows or y is 0. unchecked { if (y == 0 || (x != 0 && (x * 1e18) / 1e18 != x)) return; @@ -190,7 +190,7 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.divWadUp(x, y), x == 0 ? 0 : (x * 1e18 - 1) / y + 1); } - function testFailDivWadUpOverflow(uint256 x, uint256 y) public pure { + function testFailFuzzDivWadUpOverflow(uint256 x, uint256 y) public pure { // Ignore cases where x * WAD does not overflow or y is 0. unchecked { if (y == 0 || (x * 1e18) / 1e18 == x) revert(); @@ -199,11 +199,11 @@ contract FixedPointMathLibTest is DSTestPlus { FixedPointMathLib.divWadUp(x, y); } - function testFailDivWadUpZeroDenominator(uint256 x) public pure { + function testFailFuzzDivWadUpZeroDenominator(uint256 x) public pure { FixedPointMathLib.divWadUp(x, 0); } - function testMulDivDown( + function testFuzzMulDivDown( uint256 x, uint256 y, uint256 denominator @@ -216,7 +216,7 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.mulDivDown(x, y, denominator), (x * y) / denominator); } - function testFailMulDivDownOverflow( + function testFailFuzzMulDivDownOverflow( uint256 x, uint256 y, uint256 denominator @@ -229,11 +229,11 @@ contract FixedPointMathLibTest is DSTestPlus { FixedPointMathLib.mulDivDown(x, y, denominator); } - function testFailMulDivDownZeroDenominator(uint256 x, uint256 y) public pure { + function testFailFuzzMulDivDownZeroDenominator(uint256 x, uint256 y) public pure { FixedPointMathLib.mulDivDown(x, y, 0); } - function testMulDivUp( + function testFuzzMulDivUp( uint256 x, uint256 y, uint256 denominator @@ -246,7 +246,7 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.mulDivUp(x, y, denominator), x * y == 0 ? 0 : (x * y - 1) / denominator + 1); } - function testFailMulDivUpOverflow( + function testFailFuzzMulDivUpOverflow( uint256 x, uint256 y, uint256 denominator @@ -259,11 +259,11 @@ contract FixedPointMathLibTest is DSTestPlus { FixedPointMathLib.mulDivUp(x, y, denominator); } - function testFailMulDivUpZeroDenominator(uint256 x, uint256 y) public pure { + function testFailFuzzMulDivUpZeroDenominator(uint256 x, uint256 y) public pure { FixedPointMathLib.mulDivUp(x, y, 0); } - function testSqrt(uint256 x) public { + function testFuzzSqrt(uint256 x) public { uint256 root = FixedPointMathLib.sqrt(x); uint256 next = root + 1; diff --git a/src/test/MultiRolesAuthority.t.sol b/src/test/MultiRolesAuthority.t.sol index 85308875..98261fd5 100644 --- a/src/test/MultiRolesAuthority.t.sol +++ b/src/test/MultiRolesAuthority.t.sol @@ -156,7 +156,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertFalse(multiRolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); } - function testSetRoles(address user, uint8 role) public { + function testFuzzSetRoles(address user, uint8 role) public { assertFalse(multiRolesAuthority.doesUserHaveRole(user, role)); multiRolesAuthority.setUserRole(user, role, true); @@ -166,7 +166,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertFalse(multiRolesAuthority.doesUserHaveRole(user, role)); } - function testSetRoleCapabilities(uint8 role, bytes4 functionSig) public { + function testFuzzSetRoleCapabilities(uint8 role, bytes4 functionSig) public { assertFalse(multiRolesAuthority.doesRoleHaveCapability(role, functionSig)); multiRolesAuthority.setRoleCapability(role, functionSig, true); @@ -176,7 +176,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertFalse(multiRolesAuthority.doesRoleHaveCapability(role, functionSig)); } - function testSetPublicCapabilities(bytes4 functionSig) public { + function testFuzzSetPublicCapabilities(bytes4 functionSig) public { assertFalse(multiRolesAuthority.isCapabilityPublic(functionSig)); multiRolesAuthority.setPublicCapability(functionSig, true); @@ -186,7 +186,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertFalse(multiRolesAuthority.isCapabilityPublic(functionSig)); } - function testSetTargetCustomAuthority(address user, Authority customAuthority) public { + function testFuzzSetTargetCustomAuthority(address user, Authority customAuthority) public { assertEq(address(multiRolesAuthority.getTargetCustomAuthority(user)), address(0)); multiRolesAuthority.setTargetCustomAuthority(user, customAuthority); @@ -196,7 +196,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertEq(address(multiRolesAuthority.getTargetCustomAuthority(user)), address(0)); } - function testCanCallWithAuthorizedRole( + function testFuzzCanCallWithAuthorizedRole( address user, uint8 role, address target, @@ -220,7 +220,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertFalse(multiRolesAuthority.canCall(user, target, functionSig)); } - function testCanCallPublicCapability( + function testFuzzCanCallPublicCapability( address user, address target, bytes4 functionSig @@ -234,7 +234,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertFalse(multiRolesAuthority.canCall(user, target, functionSig)); } - function testCanCallWithCustomAuthority( + function testFuzzCanCallWithCustomAuthority( address user, address target, bytes4 functionSig @@ -257,7 +257,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertTrue(multiRolesAuthority.canCall(user, target, functionSig)); } - function testCanCallWithCustomAuthorityOverridesPublicCapability( + function testFuzzCanCallWithCustomAuthorityOverridesPublicCapability( address user, address target, bytes4 functionSig @@ -283,7 +283,7 @@ contract MultiRolesAuthorityTest is DSTestPlus { assertTrue(multiRolesAuthority.canCall(user, target, functionSig)); } - function testCanCallWithCustomAuthorityOverridesUserWithRole( + function testFuzzCanCallWithCustomAuthorityOverridesUserWithRole( address user, uint8 role, address target, diff --git a/src/test/RolesAuthority.t.sol b/src/test/RolesAuthority.t.sol index 88c43fcc..4249727c 100644 --- a/src/test/RolesAuthority.t.sol +++ b/src/test/RolesAuthority.t.sol @@ -74,7 +74,7 @@ contract RolesAuthorityTest is DSTestPlus { assertFalse(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); } - function testSetRoles(address user, uint8 role) public { + function testFuzzSetRoles(address user, uint8 role) public { assertFalse(rolesAuthority.doesUserHaveRole(user, role)); rolesAuthority.setUserRole(user, role, true); @@ -84,7 +84,7 @@ contract RolesAuthorityTest is DSTestPlus { assertFalse(rolesAuthority.doesUserHaveRole(user, role)); } - function testSetRoleCapabilities( + function testFuzzSetRoleCapabilities( uint8 role, address target, bytes4 functionSig @@ -98,7 +98,7 @@ contract RolesAuthorityTest is DSTestPlus { assertFalse(rolesAuthority.doesRoleHaveCapability(role, target, functionSig)); } - function testSetPublicCapabilities(address target, bytes4 functionSig) public { + function testFuzzSetPublicCapabilities(address target, bytes4 functionSig) public { assertFalse(rolesAuthority.isCapabilityPublic(target, functionSig)); rolesAuthority.setPublicCapability(target, functionSig, true); @@ -108,7 +108,7 @@ contract RolesAuthorityTest is DSTestPlus { assertFalse(rolesAuthority.isCapabilityPublic(target, functionSig)); } - function testCanCallWithAuthorizedRole( + function testFuzzCanCallWithAuthorizedRole( address user, uint8 role, address target, @@ -132,7 +132,7 @@ contract RolesAuthorityTest is DSTestPlus { assertFalse(rolesAuthority.canCall(user, target, functionSig)); } - function testCanCallPublicCapability( + function testFuzzCanCallPublicCapability( address user, address target, bytes4 functionSig diff --git a/src/test/SSTORE2.t.sol b/src/test/SSTORE2.t.sol index 5dbe1966..ac4232b0 100644 --- a/src/test/SSTORE2.t.sol +++ b/src/test/SSTORE2.t.sol @@ -60,14 +60,14 @@ contract SSTORE2Test is DSTestPlus { SSTORE2.read(SSTORE2.write(hex"11223344"), 41000, 42000); } - function testWriteRead(bytes calldata testBytes, bytes calldata brutalizeWith) + function testFuzzWriteRead(bytes calldata testBytes, bytes calldata brutalizeWith) public brutalizeMemory(brutalizeWith) { assertBytesEq(SSTORE2.read(SSTORE2.write(testBytes)), testBytes); } - function testWriteReadCustomStartBound( + function testFuzzWriteReadCustomStartBound( bytes calldata testBytes, uint256 startIndex, bytes calldata brutalizeWith @@ -79,7 +79,7 @@ contract SSTORE2Test is DSTestPlus { assertBytesEq(SSTORE2.read(SSTORE2.write(testBytes), startIndex), bytes(testBytes[startIndex:])); } - function testWriteReadCustomBounds( + function testFuzzWriteReadCustomBounds( bytes calldata testBytes, uint256 startIndex, uint256 endIndex, @@ -98,7 +98,7 @@ contract SSTORE2Test is DSTestPlus { ); } - function testFailReadInvalidPointer(address pointer, bytes calldata brutalizeWith) + function testFailFuzzReadInvalidPointer(address pointer, bytes calldata brutalizeWith) public view brutalizeMemory(brutalizeWith) @@ -108,7 +108,7 @@ contract SSTORE2Test is DSTestPlus { SSTORE2.read(pointer); } - function testFailReadInvalidPointerCustomStartBound( + function testFailFuzzReadInvalidPointerCustomStartBound( address pointer, uint256 startIndex, bytes calldata brutalizeWith @@ -118,7 +118,7 @@ contract SSTORE2Test is DSTestPlus { SSTORE2.read(pointer, startIndex); } - function testFailReadInvalidPointerCustomBounds( + function testFailFuzzReadInvalidPointerCustomBounds( address pointer, uint256 startIndex, uint256 endIndex, @@ -129,7 +129,7 @@ contract SSTORE2Test is DSTestPlus { SSTORE2.read(pointer, startIndex, endIndex); } - function testFailWriteReadCustomStartBoundOutOfRange( + function testFailFuzzWriteReadCustomStartBoundOutOfRange( bytes calldata testBytes, uint256 startIndex, bytes calldata brutalizeWith @@ -139,7 +139,7 @@ contract SSTORE2Test is DSTestPlus { SSTORE2.read(SSTORE2.write(testBytes), startIndex); } - function testFailWriteReadCustomBoundsOutOfRange( + function testFailFuzzWriteReadCustomBoundsOutOfRange( bytes calldata testBytes, uint256 startIndex, uint256 endIndex, diff --git a/src/test/SafeCastLib.t.sol b/src/test/SafeCastLib.t.sol index 48a2a76f..1631fbe3 100644 --- a/src/test/SafeCastLib.t.sol +++ b/src/test/SafeCastLib.t.sol @@ -87,109 +87,109 @@ contract SafeCastLibTest is DSTestPlus { SafeCastLib.safeCastTo8(type(uint8).max + 1); } - function testSafeCastTo248(uint256 x) public { + function testFuzzSafeCastTo248(uint256 x) public { x = bound(x, 0, type(uint248).max); assertEq(SafeCastLib.safeCastTo248(x), x); } - function testSafeCastTo224(uint256 x) public { + function testFuzzSafeCastTo224(uint256 x) public { x = bound(x, 0, type(uint224).max); assertEq(SafeCastLib.safeCastTo224(x), x); } - function testSafeCastTo192(uint256 x) public { + function testFuzzSafeCastTo192(uint256 x) public { x = bound(x, 0, type(uint192).max); assertEq(SafeCastLib.safeCastTo192(x), x); } - function testSafeCastTo160(uint256 x) public { + function testFuzzSafeCastTo160(uint256 x) public { x = bound(x, 0, type(uint160).max); assertEq(SafeCastLib.safeCastTo160(x), x); } - function testSafeCastTo128(uint256 x) public { + function testFuzzSafeCastTo128(uint256 x) public { x = bound(x, 0, type(uint128).max); assertEq(SafeCastLib.safeCastTo128(x), x); } - function testSafeCastTo96(uint256 x) public { + function testFuzzSafeCastTo96(uint256 x) public { x = bound(x, 0, type(uint96).max); assertEq(SafeCastLib.safeCastTo96(x), x); } - function testSafeCastTo64(uint256 x) public { + function testFuzzSafeCastTo64(uint256 x) public { x = bound(x, 0, type(uint64).max); assertEq(SafeCastLib.safeCastTo64(x), x); } - function testSafeCastTo32(uint256 x) public { + function testFuzzSafeCastTo32(uint256 x) public { x = bound(x, 0, type(uint32).max); assertEq(SafeCastLib.safeCastTo32(x), x); } - function testSafeCastTo8(uint256 x) public { + function testFuzzSafeCastTo8(uint256 x) public { x = bound(x, 0, type(uint8).max); assertEq(SafeCastLib.safeCastTo8(x), x); } - function testFailSafeCastTo248(uint256 x) public { + function testFailFuzzSafeCastTo248(uint256 x) public { x = bound(x, type(uint248).max + 1, type(uint256).max); SafeCastLib.safeCastTo248(x); } - function testFailSafeCastTo224(uint256 x) public { + function testFailFuzzSafeCastTo224(uint256 x) public { x = bound(x, type(uint224).max + 1, type(uint256).max); SafeCastLib.safeCastTo224(x); } - function testFailSafeCastTo192(uint256 x) public { + function testFailFuzzSafeCastTo192(uint256 x) public { x = bound(x, type(uint192).max + 1, type(uint256).max); SafeCastLib.safeCastTo192(x); } - function testFailSafeCastTo160(uint256 x) public { + function testFailFuzzSafeCastTo160(uint256 x) public { x = bound(x, type(uint160).max + 1, type(uint256).max); SafeCastLib.safeCastTo160(x); } - function testFailSafeCastTo128(uint256 x) public { + function testFailFuzzSafeCastTo128(uint256 x) public { x = bound(x, type(uint128).max + 1, type(uint256).max); SafeCastLib.safeCastTo128(x); } - function testFailSafeCastTo96(uint256 x) public { + function testFailFuzzSafeCastTo96(uint256 x) public { x = bound(x, type(uint96).max + 1, type(uint256).max); SafeCastLib.safeCastTo96(x); } - function testFailSafeCastTo64(uint256 x) public { + function testFailFuzzSafeCastTo64(uint256 x) public { x = bound(x, type(uint64).max + 1, type(uint256).max); SafeCastLib.safeCastTo64(x); } - function testFailSafeCastTo32(uint256 x) public { + function testFailFuzzSafeCastTo32(uint256 x) public { x = bound(x, type(uint32).max + 1, type(uint256).max); SafeCastLib.safeCastTo32(x); } - function testFailSafeCastTo8(uint256 x) public { + function testFailFuzzSafeCastTo8(uint256 x) public { x = bound(x, type(uint8).max + 1, type(uint256).max); SafeCastLib.safeCastTo8(x); diff --git a/src/test/SafeTransferLib.t.sol b/src/test/SafeTransferLib.t.sol index ebae33a3..2cbcd3c2 100644 --- a/src/test/SafeTransferLib.t.sol +++ b/src/test/SafeTransferLib.t.sol @@ -127,7 +127,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(returnsTooLittle), address(0xBEEF), 1e18); } - function testTransferWithMissingReturn( + function testFuzzTransferWithMissingReturn( address to, uint256 amount, bytes calldata brutalizeWith @@ -135,7 +135,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(missingReturn), to, amount); } - function testTransferWithStandardERC20( + function testFuzzTransferWithStandardERC20( address to, uint256 amount, bytes calldata brutalizeWith @@ -143,7 +143,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(erc20), to, amount); } - function testTransferWithReturnsTooMuch( + function testFuzzTransferWithReturnsTooMuch( address to, uint256 amount, bytes calldata brutalizeWith @@ -151,7 +151,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(returnsTooMuch), to, amount); } - function testTransferWithGarbage( + function testFuzzTransferWithGarbage( address to, uint256 amount, bytes memory garbage, @@ -198,7 +198,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(returnsGarbage), to, amount); } - function testTransferWithNonContract( + function testFuzzTransferWithNonContract( address nonContract, address to, uint256 amount, @@ -213,7 +213,7 @@ contract SafeTransferLibTest is DSTestPlus { SafeTransferLib.safeTransferETH(address(this), 1e18); } - function testTransferFromWithMissingReturn( + function testFuzzTransferFromWithMissingReturn( address from, address to, uint256 amount, @@ -222,7 +222,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(missingReturn), from, to, amount); } - function testTransferFromWithStandardERC20( + function testFuzzTransferFromWithStandardERC20( address from, address to, uint256 amount, @@ -231,7 +231,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(erc20), from, to, amount); } - function testTransferFromWithReturnsTooMuch( + function testFuzzTransferFromWithReturnsTooMuch( address from, address to, uint256 amount, @@ -240,7 +240,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(returnsTooMuch), from, to, amount); } - function testTransferFromWithGarbage( + function testFuzzTransferFromWithGarbage( address from, address to, uint256 amount, @@ -288,7 +288,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(returnsGarbage), from, to, amount); } - function testTransferFromWithNonContract( + function testFuzzTransferFromWithNonContract( address nonContract, address from, address to, @@ -300,7 +300,7 @@ contract SafeTransferLibTest is DSTestPlus { SafeTransferLib.safeTransferFrom(ERC20(nonContract), from, to, amount); } - function testApproveWithMissingReturn( + function testFuzzApproveWithMissingReturn( address to, uint256 amount, bytes calldata brutalizeWith @@ -308,7 +308,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(missingReturn), to, amount); } - function testApproveWithStandardERC20( + function testFuzzApproveWithStandardERC20( address to, uint256 amount, bytes calldata brutalizeWith @@ -316,7 +316,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(erc20), to, amount); } - function testApproveWithReturnsTooMuch( + function testFuzzApproveWithReturnsTooMuch( address to, uint256 amount, bytes calldata brutalizeWith @@ -324,7 +324,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(returnsTooMuch), to, amount); } - function testApproveWithGarbage( + function testFuzzApproveWithGarbage( address to, uint256 amount, bytes memory garbage, @@ -371,7 +371,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(returnsGarbage), to, amount); } - function testApproveWithNonContract( + function testFuzzApproveWithNonContract( address nonContract, address to, uint256 amount, @@ -382,7 +382,7 @@ contract SafeTransferLibTest is DSTestPlus { SafeTransferLib.safeApprove(ERC20(nonContract), to, amount); } - function testTransferETH( + function testFuzzTransferETH( address recipient, uint256 amount, bytes calldata brutalizeWith @@ -395,7 +395,7 @@ contract SafeTransferLibTest is DSTestPlus { SafeTransferLib.safeTransferETH(recipient, amount); } - function testFailTransferWithReturnsFalse( + function testFailFuzzTransferWithReturnsFalse( address to, uint256 amount, bytes calldata brutalizeWith @@ -403,7 +403,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(returnsFalse), to, amount); } - function testFailTransferWithReverting( + function testFailFuzzTransferWithReverting( address to, uint256 amount, bytes calldata brutalizeWith @@ -411,7 +411,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(reverting), to, amount); } - function testFailTransferWithReturnsTooLittle( + function testFailFuzzTransferWithReturnsTooLittle( address to, uint256 amount, bytes calldata brutalizeWith @@ -419,7 +419,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(returnsTooLittle), to, amount); } - function testFailTransferWithReturnsTwo( + function testFailFuzzTransferWithReturnsTwo( address to, uint256 amount, bytes calldata brutalizeWith @@ -427,7 +427,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(returnsTwo), to, amount); } - function testFailTransferWithGarbage( + function testFailFuzzTransferWithGarbage( address to, uint256 amount, bytes memory garbage, @@ -440,7 +440,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransfer(address(returnsGarbage), to, amount); } - function testFailTransferFromWithReturnsFalse( + function testFailFuzzTransferFromWithReturnsFalse( address from, address to, uint256 amount, @@ -449,7 +449,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(returnsFalse), from, to, amount); } - function testFailTransferFromWithReverting( + function testFailFuzzTransferFromWithReverting( address from, address to, uint256 amount, @@ -458,7 +458,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(reverting), from, to, amount); } - function testFailTransferFromWithReturnsTooLittle( + function testFailFuzzTransferFromWithReturnsTooLittle( address from, address to, uint256 amount, @@ -467,7 +467,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(returnsTooLittle), from, to, amount); } - function testFailTransferFromWithReturnsTwo( + function testFailFuzzTransferFromWithReturnsTwo( address from, address to, uint256 amount, @@ -476,7 +476,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(returnsTwo), from, to, amount); } - function testFailTransferFromWithGarbage( + function testFailFuzzTransferFromWithGarbage( address from, address to, uint256 amount, @@ -490,7 +490,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeTransferFrom(address(returnsGarbage), from, to, amount); } - function testFailApproveWithReturnsFalse( + function testFailFuzzApproveWithReturnsFalse( address to, uint256 amount, bytes calldata brutalizeWith @@ -498,7 +498,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(returnsFalse), to, amount); } - function testFailApproveWithReverting( + function testFailFuzzApproveWithReverting( address to, uint256 amount, bytes calldata brutalizeWith @@ -506,7 +506,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(reverting), to, amount); } - function testFailApproveWithReturnsTooLittle( + function testFailFuzzApproveWithReturnsTooLittle( address to, uint256 amount, bytes calldata brutalizeWith @@ -514,7 +514,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(returnsTooLittle), to, amount); } - function testFailApproveWithReturnsTwo( + function testFailFuzzApproveWithReturnsTwo( address to, uint256 amount, bytes calldata brutalizeWith @@ -522,7 +522,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(returnsTwo), to, amount); } - function testFailApproveWithGarbage( + function testFailFuzzApproveWithGarbage( address to, uint256 amount, bytes memory garbage, @@ -535,7 +535,7 @@ contract SafeTransferLibTest is DSTestPlus { verifySafeApprove(address(returnsGarbage), to, amount); } - function testFailTransferETHToContractWithoutFallback(uint256 amount, bytes calldata brutalizeWith) + function testFailFuzzTransferETHToContractWithoutFallback(uint256 amount, bytes calldata brutalizeWith) public brutalizeMemory(brutalizeWith) { diff --git a/src/test/WETH.t.sol b/src/test/WETH.t.sol index f2d8b9e1..807a8fbf 100644 --- a/src/test/WETH.t.sol +++ b/src/test/WETH.t.sol @@ -63,7 +63,7 @@ contract WETHTest is DSTestPlus { assertEq(weth.totalSupply(), 0.5 ether); } - function testDeposit(uint256 amount) public { + function testFuzzDeposit(uint256 amount) public { amount = bound(amount, 0, address(this).balance); assertEq(weth.balanceOf(address(this)), 0); @@ -75,7 +75,7 @@ contract WETHTest is DSTestPlus { assertEq(weth.totalSupply(), amount); } - function testFallbackDeposit(uint256 amount) public { + function testFuzzFallbackDeposit(uint256 amount) public { amount = bound(amount, 0, address(this).balance); assertEq(weth.balanceOf(address(this)), 0); @@ -87,7 +87,7 @@ contract WETHTest is DSTestPlus { assertEq(weth.totalSupply(), amount); } - function testWithdraw(uint256 depositAmount, uint256 withdrawAmount) public { + function testFuzzWithdraw(uint256 depositAmount, uint256 withdrawAmount) public { depositAmount = bound(depositAmount, 0, address(this).balance); withdrawAmount = bound(withdrawAmount, 0, depositAmount); From bc62c2e409311640700ddfefc1a5b064c3d5ef3b Mon Sep 17 00:00:00 2001 From: Rajiv Patel-O'Connor Date: Fri, 13 May 2022 00:50:10 -0400 Subject: [PATCH 06/44] =?UTF-8?q?=E2=9C=A8=20Merkle=20Lib=20(#151)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- src/test/MerkleProof.t.sol | 44 ++++++++++++++++++++++++++++++++++++++ src/utils/MerkleProof.sol | 43 +++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/test/MerkleProof.t.sol create mode 100644 src/utils/MerkleProof.sol diff --git a/.gitignore b/.gitignore index 5dfe93fb..3b893825 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /cache /node_modules -/out \ No newline at end of file +/out +.DS_STORE \ No newline at end of file diff --git a/src/test/MerkleProof.t.sol b/src/test/MerkleProof.t.sol new file mode 100644 index 00000000..cbfb562c --- /dev/null +++ b/src/test/MerkleProof.t.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity 0.8.10; + +import {DSTestPlus} from "./utils/DSTestPlus.sol"; + +import {MerkleProof} from "../utils/MerkleProof.sol"; + +contract MerkleProofTest is DSTestPlus { + function testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() public { + bytes32[] memory proof; + assertBoolEq(MerkleProof.verify(proof, 0x00, 0x00), true); + } + + function testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() public { + bytes32[] memory proof; + bytes32 leaf = "a"; + assertBoolEq(MerkleProof.verify(proof, 0x00, leaf), false); + } + + function testValidProofSupplied() public { + // Merkle tree created from leaves ['a', 'b', 'c']. + // Leaf is 'a'. + bytes32[] memory proof = new bytes32[](2); + proof[0] = 0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510; + proof[1] = 0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2; + bytes32 root = 0x5842148bc6ebeb52af882a317c765fccd3ae80589b21a9b8cbf21abb630e46a7; + bytes32 leaf = 0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb; + assertBoolEq(MerkleProof.verify(proof, root, leaf), true); + } + + function testVerifyInvalidProofSupplied() public { + // Merkle tree created from leaves ['a', 'b', 'c']. + // Leaf is 'a'. + // Proof is same as testValidProofSupplied but last byte of first element is modified. + bytes32[] memory proof = new bytes32[](2); + proof[0] = 0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5511; + proof[1] = 0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2; + bytes32 root = 0x5842148bc6ebeb52af882a317c765fccd3ae80589b21a9b8cbf21abb630e46a7; + bytes32 leaf = 0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb; + assertBoolEq(MerkleProof.verify(proof, root, leaf), false); + } + + +} diff --git a/src/utils/MerkleProof.sol b/src/utils/MerkleProof.sol new file mode 100644 index 00000000..86eeebe5 --- /dev/null +++ b/src/utils/MerkleProof.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/MerkleProof.sol) +/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) +library MerkleProof { + function verify( + bytes32[] memory proof, + bytes32 root, + bytes32 leaf + ) internal pure returns (bool isValid) { + assembly { + let computedHash := leaf + + // Get the memory start location of the first element in the proof array. + let data := add(proof, 0x20) + + // Iterate over proof elements to compute root hash. + for { + let end := add(data, mul(mload(proof), 0x20)) + } lt(data, end) { + data := add(data, 0x20) + } { + let loadedData := mload(data) + switch gt(computedHash, loadedData) + case 0 { + // Store elements to hash contiguously in scratch space. + // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. + mstore(0x00, computedHash) + mstore(0x20, loadedData) + computedHash := keccak256(0x00, 0x40) + } + default { + mstore(0x00, loadedData) + mstore(0x20, computedHash) + computedHash := keccak256(0x00, 0x40) + } + } + isValid := eq(computedHash, root) + } + } +} From 4946f52f1b21b19b3edba0244ff765a4681e2df2 Mon Sep 17 00:00:00 2001 From: wilsoncusack Date: Thu, 12 May 2022 23:58:09 -0500 Subject: [PATCH 07/44] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Optimize=20ERC721=20?= =?UTF-8?q?jumps=20(#184)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: t11s --- .gas-snapshot | 36 ++++++++++++++++++------------------ src/tokens/ERC721.sol | 40 ++++++++++++++++++++-------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index d0bb1145..ce1f695b 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -100,29 +100,29 @@ ERC721Test:testFailDoubleBurn() (gas: 58943) ERC721Test:testFailDoubleMint() (gas: 53286) ERC721Test:testFailMintToZero() (gas: 5753) ERC721Test:testFailOwnerOfUnminted() (gas: 7609) -ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnData() (gas: 159076) -ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnDataWithData() (gas: 159831) -ERC721Test:testFailSafeMintToNonERC721Recipient() (gas: 89210) -ERC721Test:testFailSafeMintToNonERC721RecipientWithData() (gas: 89995) -ERC721Test:testFailSafeMintToRevertingERC721Recipient() (gas: 204743) -ERC721Test:testFailSafeMintToRevertingERC721RecipientWithData() (gas: 205517) -ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnData() (gas: 187276) -ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData() (gas: 187728) -ERC721Test:testFailSafeTransferFromToNonERC721Recipient() (gas: 117413) -ERC721Test:testFailSafeTransferFromToNonERC721RecipientWithData() (gas: 117872) -ERC721Test:testFailSafeTransferFromToRevertingERC721Recipient() (gas: 233009) -ERC721Test:testFailSafeTransferFromToRevertingERC721RecipientWithData() (gas: 233396) +ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnData() (gas: 159070) +ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnDataWithData() (gas: 159825) +ERC721Test:testFailSafeMintToNonERC721Recipient() (gas: 89205) +ERC721Test:testFailSafeMintToNonERC721RecipientWithData() (gas: 89990) +ERC721Test:testFailSafeMintToRevertingERC721Recipient() (gas: 204738) +ERC721Test:testFailSafeMintToRevertingERC721RecipientWithData() (gas: 205512) +ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnData() (gas: 187270) +ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData() (gas: 187722) +ERC721Test:testFailSafeTransferFromToNonERC721Recipient() (gas: 117408) +ERC721Test:testFailSafeTransferFromToNonERC721RecipientWithData() (gas: 117867) +ERC721Test:testFailSafeTransferFromToRevertingERC721Recipient() (gas: 233004) +ERC721Test:testFailSafeTransferFromToRevertingERC721RecipientWithData() (gas: 233391) ERC721Test:testFailTransferFromNotOwner() (gas: 57872) ERC721Test:testFailTransferFromToZero() (gas: 53381) ERC721Test:testFailTransferFromUnOwned() (gas: 8000) ERC721Test:testFailTransferFromWrongFrom() (gas: 53361) ERC721Test:testMint() (gas: 54336) -ERC721Test:testSafeMintToEOA() (gas: 56993) -ERC721Test:testSafeMintToERC721Recipient() (gas: 381737) -ERC721Test:testSafeMintToERC721RecipientWithData() (gas: 402881) -ERC721Test:testSafeTransferFromToEOA() (gas: 95666) -ERC721Test:testSafeTransferFromToERC721Recipient() (gas: 440251) -ERC721Test:testSafeTransferFromToERC721RecipientWithData() (gas: 461049) +ERC721Test:testSafeMintToEOA() (gas: 56976) +ERC721Test:testSafeMintToERC721Recipient() (gas: 381731) +ERC721Test:testSafeMintToERC721RecipientWithData() (gas: 402875) +ERC721Test:testSafeTransferFromToEOA() (gas: 95649) +ERC721Test:testSafeTransferFromToERC721Recipient() (gas: 440245) +ERC721Test:testSafeTransferFromToERC721RecipientWithData() (gas: 461043) ERC721Test:testTransferFrom() (gas: 86347) ERC721Test:testTransferFromApproveAll() (gas: 92898) ERC721Test:testTransferFromSelf() (gas: 64776) diff --git a/src/tokens/ERC721.sol b/src/tokens/ERC721.sol index 13309b73..f93d993a 100644 --- a/src/tokens/ERC721.sol +++ b/src/tokens/ERC721.sol @@ -115,12 +115,12 @@ abstract contract ERC721 { ) public virtual { transferFrom(from, to, id); - require( - to.code.length == 0 || + if (to.code.length != 0) + require( ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == - ERC721TokenReceiver.onERC721Received.selector, - "UNSAFE_RECIPIENT" - ); + ERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); } function safeTransferFrom( @@ -131,12 +131,12 @@ abstract contract ERC721 { ) public virtual { transferFrom(from, to, id); - require( - to.code.length == 0 || + if (to.code.length != 0) + require( ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == - ERC721TokenReceiver.onERC721Received.selector, - "UNSAFE_RECIPIENT" - ); + ERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); } /*////////////////////////////////////////////////////////////// @@ -193,12 +193,12 @@ abstract contract ERC721 { function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); - require( - to.code.length == 0 || + if (to.code.length != 0) + require( ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == - ERC721TokenReceiver.onERC721Received.selector, - "UNSAFE_RECIPIENT" - ); + ERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); } function _safeMint( @@ -208,12 +208,12 @@ abstract contract ERC721 { ) internal virtual { _mint(to, id); - require( - to.code.length == 0 || + if (to.code.length != 0) + require( ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == - ERC721TokenReceiver.onERC721Received.selector, - "UNSAFE_RECIPIENT" - ); + ERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); } } From e84ccc786dbe807484bfaf06bb4feed0b6266ee9 Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 12 May 2022 22:01:00 -0700 Subject: [PATCH 08/44] =?UTF-8?q?=E2=9C=A8=20ERC1155B=20(#192)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 36 + src/test/ERC1155B.t.sol | 1595 +++++++++++++++++++++++++ src/test/utils/mocks/MockERC1155B.sol | 32 + src/test/utils/users/ERC1155BUser.sol | 57 + src/tokens/ERC1155B.sol | 260 ++++ 5 files changed, 1980 insertions(+) create mode 100644 src/test/ERC1155B.t.sol create mode 100644 src/test/utils/mocks/MockERC1155B.sol create mode 100644 src/test/utils/users/ERC1155BUser.sol create mode 100644 src/tokens/ERC1155B.sol diff --git a/.gas-snapshot b/.gas-snapshot index ce1f695b..1a91e953 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -61,6 +61,42 @@ ERC1155Test:testSafeBatchTransferFromToERC1155Recipient() (gas: 1122274) ERC1155Test:testSafeTransferFromSelf() (gas: 64177) ERC1155Test:testSafeTransferFromToEOA() (gas: 93167) ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 686500) +ERC1155BTest:testApproveAll() (gas: 30947) +ERC1155BTest:testBatchBalanceOf() (gas: 157240) +ERC1155BTest:testBatchBurn() (gas: 114460) +ERC1155BTest:testBatchMintToEOA() (gas: 135755) +ERC1155BTest:testBatchMintToERC1155Recipient() (gas: 941538) +ERC1155BTest:testBurn() (gas: 26508) +ERC1155BTest:testFailBalanceOfBatchWithArrayMismatch() (gas: 7933) +ERC1155BTest:testFailBatchBurnInsufficientBalance() (gas: 10052) +ERC1155BTest:testFailBatchMintToNonERC1155Recipient() (gas: 166023) +ERC1155BTest:testFailBatchMintToRevertingERC1155Recipient() (gas: 357584) +ERC1155BTest:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 309471) +ERC1155BTest:testFailBatchMintToZero() (gas: 30941) +ERC1155BTest:testFailBurnInsufficientBalance() (gas: 7768) +ERC1155BTest:testFailMintToNonERC1155Recipient() (gas: 68217) +ERC1155BTest:testFailMintToRevertingERC1155Recipient() (gas: 259420) +ERC1155BTest:testFailMintToWrongReturnDataERC1155Recipient() (gas: 259419) +ERC1155BTest:testFailMintToZero() (gas: 13766) +ERC1155BTest:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 722319) +ERC1155BTest:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 913812) +ERC1155BTest:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 865743) +ERC1155BTest:testFailSafeBatchTransferFromToZero() (gas: 687476) +ERC1155BTest:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 674842) +ERC1155BTest:testFailSafeBatchTransferInsufficientBalance() (gas: 552088) +ERC1155BTest:testFailSafeTransferFromInsufficientBalance() (gas: 549469) +ERC1155BTest:testFailSafeTransferFromSelfInsufficientBalance() (gas: 8381) +ERC1155BTest:testFailSafeTransferFromToNonERC1155Recipient() (gas: 74204) +ERC1155BTest:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 265404) +ERC1155BTest:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 217275) +ERC1155BTest:testFailSafeTransferFromToZero() (gas: 8362) +ERC1155BTest:testMintToEOA() (gas: 34642) +ERC1155BTest:testMintToERC1155Recipient() (gas: 608200) +ERC1155BTest:testSafeBatchTransferFromToEOA() (gas: 698170) +ERC1155BTest:testSafeBatchTransferFromToERC1155Recipient() (gas: 1522381) +ERC1155BTest:testSafeTransferFromSelf() (gas: 41780) +ERC1155BTest:testSafeTransferFromToEOA() (gas: 582836) +ERC1155BTest:testSafeTransferFromToERC1155Recipient() (gas: 1175937) ERC20Test:testApprove() (gas: 31058) ERC20Test:testBurn() (gas: 56970) ERC20Test:testFailPermitBadDeadline() (gas: 36924) diff --git a/src/test/ERC1155B.t.sol b/src/test/ERC1155B.t.sol new file mode 100644 index 00000000..1dc3aca4 --- /dev/null +++ b/src/test/ERC1155B.t.sol @@ -0,0 +1,1595 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity 0.8.10; + +import {DSTestPlus} from "./utils/DSTestPlus.sol"; +import {DSInvariantTest} from "./utils/DSInvariantTest.sol"; + +import {MockERC1155B} from "./utils/mocks/MockERC1155B.sol"; +import {ERC1155BUser} from "./utils/users/ERC1155BUser.sol"; + +import {ERC1155TokenReceiver} from "../tokens/ERC1155.sol"; + +// TODO: test invalid_amount errors +// TODO: test ownerOf() +// TODO: fuzz testing +// TODO: test custom safe batch transfer +// TODO: test cant burn unminted tokens + +contract ERC1155BRecipient is ERC1155TokenReceiver { + address public operator; + address public from; + uint256 public id; + uint256 public amount; + bytes public mintData; + + function onERC1155Received( + address _operator, + address _from, + uint256 _id, + uint256 _amount, + bytes calldata _data + ) public override returns (bytes4) { + operator = _operator; + from = _from; + id = _id; + amount = _amount; + mintData = _data; + + return ERC1155TokenReceiver.onERC1155Received.selector; + } + + address public batchOperator; + address public batchFrom; + uint256[] internal _batchIds; + uint256[] internal _batchAmounts; + bytes public batchData; + + function batchIds() external view returns (uint256[] memory) { + return _batchIds; + } + + function batchAmounts() external view returns (uint256[] memory) { + return _batchAmounts; + } + + function onERC1155BatchReceived( + address _operator, + address _from, + uint256[] calldata _ids, + uint256[] calldata _amounts, + bytes calldata _data + ) external override returns (bytes4) { + batchOperator = _operator; + batchFrom = _from; + _batchIds = _ids; + _batchAmounts = _amounts; + batchData = _data; + + return ERC1155TokenReceiver.onERC1155BatchReceived.selector; + } +} + +contract RevertingERC1155Recipient is ERC1155TokenReceiver { + function onERC1155Received( + address, + address, + uint256, + uint256, + bytes calldata + ) public pure override returns (bytes4) { + revert(string(abi.encodePacked(ERC1155TokenReceiver.onERC1155Received.selector))); + } + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external pure override returns (bytes4) { + revert(string(abi.encodePacked(ERC1155TokenReceiver.onERC1155BatchReceived.selector))); + } +} + +contract WrongReturnDataERC1155BRecipient is ERC1155TokenReceiver { + function onERC1155Received( + address, + address, + uint256, + uint256, + bytes calldata + ) public pure override returns (bytes4) { + return 0xCAFEBEEF; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external pure override returns (bytes4) { + return 0xCAFEBEEF; + } +} + +contract NonERC1155BRecipient {} + +contract ERC1155BTest is DSTestPlus, ERC1155TokenReceiver { + MockERC1155B token; + + mapping(address => mapping(uint256 => uint256)) public userMintAmounts; + mapping(address => mapping(uint256 => uint256)) public userTransferOrBurnAmounts; + + function setUp() public { + token = new MockERC1155B(); + } + + function testMintToEOA() public { + token.mint(address(0xBEEF), 1337, ""); + + assertEq(token.balanceOf(address(0xBEEF), 1337), 1); + } + + function testMintToERC1155Recipient() public { + ERC1155BRecipient to = new ERC1155BRecipient(); + + token.mint(address(to), 1337, "testing 123"); + + assertEq(token.balanceOf(address(to), 1337), 1); + + assertEq(to.operator(), address(this)); + assertEq(to.from(), address(0)); + assertEq(to.id(), 1337); + assertBytesEq(to.mintData(), "testing 123"); + } + + function testBatchMintToEOA() public { + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + token.batchMint(address(0xBEEF), ids, ""); + + assertEq(token.balanceOf(address(0xBEEF), 1337), 1); + assertEq(token.balanceOf(address(0xBEEF), 1338), 1); + assertEq(token.balanceOf(address(0xBEEF), 1339), 1); + assertEq(token.balanceOf(address(0xBEEF), 1340), 1); + assertEq(token.balanceOf(address(0xBEEF), 1341), 1); + } + + function testBatchMintToERC1155Recipient() public { + ERC1155BRecipient to = new ERC1155BRecipient(); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory amounts = new uint256[](5); + amounts[0] = 1; + amounts[1] = 1; + amounts[2] = 1; + amounts[3] = 1; + amounts[4] = 1; + + token.batchMint(address(to), ids, "testing 123"); + + assertEq(to.batchOperator(), address(this)); + assertEq(to.batchFrom(), address(0)); + assertUintArrayEq(to.batchIds(), ids); + assertUintArrayEq(to.batchAmounts(), amounts); + assertBytesEq(to.batchData(), "testing 123"); + + assertEq(token.balanceOf(address(to), 1337), 1); + assertEq(token.balanceOf(address(to), 1338), 1); + assertEq(token.balanceOf(address(to), 1339), 1); + assertEq(token.balanceOf(address(to), 1340), 1); + assertEq(token.balanceOf(address(to), 1341), 1); + } + + function testBurn() public { + token.mint(address(0xBEEF), 1337, ""); + + token.burn(1337); + + assertEq(token.balanceOf(address(0xBEEF), 1337), 0); + } + + function testBatchBurn() public { + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + token.batchMint(address(0xBEEF), ids, ""); + + token.batchBurn(address(0xBEEF), ids); + + assertEq(token.balanceOf(address(0xBEEF), 1337), 0); + assertEq(token.balanceOf(address(0xBEEF), 1338), 0); + assertEq(token.balanceOf(address(0xBEEF), 1339), 0); + assertEq(token.balanceOf(address(0xBEEF), 1340), 0); + assertEq(token.balanceOf(address(0xBEEF), 1341), 0); + } + + function testApproveAll() public { + token.setApprovalForAll(address(0xBEEF), true); + + assertTrue(token.isApprovedForAll(address(this), address(0xBEEF))); + } + + function testSafeTransferFromToEOA() public { + ERC1155BUser from = new ERC1155BUser(token); + + token.mint(address(from), 1337, ""); + + from.setApprovalForAll(address(this), true); + + token.safeTransferFrom(address(from), address(0xBEEF), 1337, 1, ""); + + assertEq(token.balanceOf(address(0xBEEF), 1337), 1); + assertEq(token.balanceOf(address(from), 1337), 0); + } + + function testSafeTransferFromToERC1155Recipient() public { + ERC1155BRecipient to = new ERC1155BRecipient(); + + ERC1155BUser from = new ERC1155BUser(token); + + token.mint(address(from), 1337, ""); + + from.setApprovalForAll(address(this), true); + + token.safeTransferFrom(address(from), address(to), 1337, 1, "testing 123"); + + assertEq(to.operator(), address(this)); + assertEq(to.from(), address(from)); + assertEq(to.id(), 1337); + assertBytesEq(to.mintData(), "testing 123"); + + assertEq(token.balanceOf(address(to), 1337), 1); + assertEq(token.balanceOf(address(from), 1337), 0); + } + + function testSafeTransferFromSelf() public { + token.mint(address(this), 1337, ""); + + token.safeTransferFrom(address(this), address(0xBEEF), 1337, 1, ""); + + assertEq(token.balanceOf(address(0xBEEF), 1337), 1); + assertEq(token.balanceOf(address(this), 1337), 0); + } + + function testSafeBatchTransferFromToEOA() public { + ERC1155BUser from = new ERC1155BUser(token); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory transferAmounts = new uint256[](5); + transferAmounts[0] = 1; + transferAmounts[1] = 1; + transferAmounts[2] = 1; + transferAmounts[3] = 1; + transferAmounts[4] = 1; + + token.batchMint(address(from), ids, ""); + + from.setApprovalForAll(address(this), true); + + token.safeBatchTransferFrom(address(from), address(0xBEEF), ids, transferAmounts, ""); + + assertEq(token.balanceOf(address(from), 1337), 0); + assertEq(token.balanceOf(address(0xBEEF), 1337), 1); + + assertEq(token.balanceOf(address(from), 1338), 0); + assertEq(token.balanceOf(address(0xBEEF), 1338), 1); + + assertEq(token.balanceOf(address(from), 1339), 0); + assertEq(token.balanceOf(address(0xBEEF), 1339), 1); + + assertEq(token.balanceOf(address(from), 1340), 0); + assertEq(token.balanceOf(address(0xBEEF), 1340), 1); + + assertEq(token.balanceOf(address(from), 1341), 0); + assertEq(token.balanceOf(address(0xBEEF), 1341), 1); + } + + function testSafeBatchTransferFromToERC1155Recipient() public { + ERC1155BUser from = new ERC1155BUser(token); + + ERC1155BRecipient to = new ERC1155BRecipient(); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory transferAmounts = new uint256[](5); + transferAmounts[0] = 1; + transferAmounts[1] = 1; + transferAmounts[2] = 1; + transferAmounts[3] = 1; + transferAmounts[4] = 1; + + token.batchMint(address(from), ids, ""); + + from.setApprovalForAll(address(this), true); + + token.safeBatchTransferFrom(address(from), address(to), ids, transferAmounts, "testing 123"); + + assertEq(to.batchOperator(), address(this)); + assertEq(to.batchFrom(), address(from)); + assertUintArrayEq(to.batchIds(), ids); + assertUintArrayEq(to.batchAmounts(), transferAmounts); + assertBytesEq(to.batchData(), "testing 123"); + + assertEq(token.balanceOf(address(from), 1337), 0); + assertEq(token.balanceOf(address(to), 1337), 1); + + assertEq(token.balanceOf(address(from), 1338), 0); + assertEq(token.balanceOf(address(to), 1338), 1); + + assertEq(token.balanceOf(address(from), 1339), 0); + assertEq(token.balanceOf(address(to), 1339), 1); + + assertEq(token.balanceOf(address(from), 1340), 0); + assertEq(token.balanceOf(address(to), 1340), 1); + + assertEq(token.balanceOf(address(from), 1341), 0); + assertEq(token.balanceOf(address(to), 1341), 1); + } + + function testBatchBalanceOf() public { + address[] memory tos = new address[](5); + tos[0] = address(0xBEEF); + tos[1] = address(0xCAFE); + tos[2] = address(0xFACE); + tos[3] = address(0xDEAD); + tos[4] = address(0xFEED); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + token.mint(address(0xBEEF), 1337, ""); + token.mint(address(0xCAFE), 1338, ""); + token.mint(address(0xFACE), 1339, ""); + token.mint(address(0xDEAD), 1340, ""); + token.mint(address(0xFEED), 1341, ""); + + uint256[] memory balances = token.balanceOfBatch(tos, ids); + + assertEq(balances[0], 1); + assertEq(balances[1], 1); + assertEq(balances[2], 1); + assertEq(balances[3], 1); + assertEq(balances[4], 1); + } + + function testFailMintToZero() public { + token.mint(address(0), 1337, ""); + } + + function testFailMintToNonERC1155Recipient() public { + token.mint(address(new NonERC1155BRecipient()), 1337, ""); + } + + function testFailMintToRevertingERC1155Recipient() public { + token.mint(address(new RevertingERC1155Recipient()), 1337, ""); + } + + function testFailMintToWrongReturnDataERC1155Recipient() public { + token.mint(address(new RevertingERC1155Recipient()), 1337, ""); + } + + function testFailBurnInsufficientBalance() public { + token.burn(1337); + } + + function testFailSafeTransferFromInsufficientBalance() public { + ERC1155BUser from = new ERC1155BUser(token); + + from.setApprovalForAll(address(this), true); + + token.safeTransferFrom(address(from), address(0xBEEF), 1337, 1, ""); + } + + function testFailSafeTransferFromSelfInsufficientBalance() public { + token.safeTransferFrom(address(this), address(0xBEEF), 1337, 1, ""); + } + + function testFailSafeTransferFromToZero() public { + token.safeTransferFrom(address(this), address(0), 1337, 1, ""); + } + + function testFailSafeTransferFromToNonERC1155Recipient() public { + token.mint(address(this), 1337, ""); + token.safeTransferFrom(address(this), address(new NonERC1155BRecipient()), 1337, 1, ""); + } + + function testFailSafeTransferFromToRevertingERC1155Recipient() public { + token.mint(address(this), 1337, ""); + token.safeTransferFrom(address(this), address(new RevertingERC1155Recipient()), 1337, 1, ""); + } + + function testFailSafeTransferFromToWrongReturnDataERC1155Recipient() public { + token.mint(address(this), 1337, ""); + token.safeTransferFrom(address(this), address(new WrongReturnDataERC1155BRecipient()), 1337, 1, ""); + } + + function testFailSafeBatchTransferInsufficientBalance() public { + ERC1155BUser from = new ERC1155BUser(token); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory transferAmounts = new uint256[](5); + transferAmounts[0] = 1; + transferAmounts[1] = 1; + transferAmounts[2] = 1; + transferAmounts[3] = 1; + transferAmounts[4] = 1; + + from.setApprovalForAll(address(this), true); + + token.safeBatchTransferFrom(address(from), address(0xBEEF), ids, transferAmounts, ""); + } + + function testFailSafeBatchTransferFromToZero() public { + ERC1155BUser from = new ERC1155BUser(token); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory transferAmounts = new uint256[](5); + transferAmounts[0] = 1; + transferAmounts[1] = 1; + transferAmounts[2] = 1; + transferAmounts[3] = 1; + transferAmounts[4] = 1; + + token.batchMint(address(from), ids, ""); + + from.setApprovalForAll(address(this), true); + + token.safeBatchTransferFrom(address(from), address(0), ids, transferAmounts, ""); + } + + function testFailSafeBatchTransferFromToNonERC1155Recipient() public { + ERC1155BUser from = new ERC1155BUser(token); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory transferAmounts = new uint256[](5); + transferAmounts[0] = 1; + transferAmounts[1] = 1; + transferAmounts[2] = 1; + transferAmounts[3] = 1; + transferAmounts[4] = 1; + + token.batchMint(address(from), ids, ""); + + from.setApprovalForAll(address(this), true); + + token.safeBatchTransferFrom(address(from), address(new NonERC1155BRecipient()), ids, transferAmounts, ""); + } + + function testFailSafeBatchTransferFromToRevertingERC1155Recipient() public { + ERC1155BUser from = new ERC1155BUser(token); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory transferAmounts = new uint256[](5); + transferAmounts[0] = 1; + transferAmounts[1] = 1; + transferAmounts[2] = 1; + transferAmounts[3] = 1; + transferAmounts[4] = 1; + + token.batchMint(address(from), ids, ""); + + from.setApprovalForAll(address(this), true); + + token.safeBatchTransferFrom(address(from), address(new RevertingERC1155Recipient()), ids, transferAmounts, ""); + } + + function testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() public { + ERC1155BUser from = new ERC1155BUser(token); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory transferAmounts = new uint256[](5); + transferAmounts[0] = 1; + transferAmounts[1] = 1; + transferAmounts[2] = 1; + transferAmounts[3] = 1; + transferAmounts[4] = 1; + + token.batchMint(address(from), ids, ""); + + from.setApprovalForAll(address(this), true); + + token.safeBatchTransferFrom( + address(from), + address(new WrongReturnDataERC1155BRecipient()), + ids, + transferAmounts, + "" + ); + } + + function testFailSafeBatchTransferFromWithArrayLengthMismatch() public { + ERC1155BUser from = new ERC1155BUser(token); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + uint256[] memory transferAmounts = new uint256[](4); + transferAmounts[0] = 1; + transferAmounts[1] = 1; + transferAmounts[2] = 1; + transferAmounts[3] = 1; + + token.batchMint(address(from), ids, ""); + + from.setApprovalForAll(address(this), true); + + token.safeBatchTransferFrom(address(from), address(0xBEEF), ids, transferAmounts, ""); + } + + function testFailBatchMintToZero() public { + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + token.batchMint(address(0), ids, ""); + } + + function testFailBatchMintToNonERC1155Recipient() public { + NonERC1155BRecipient to = new NonERC1155BRecipient(); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + token.batchMint(address(to), ids, ""); + } + + function testFailBatchMintToRevertingERC1155Recipient() public { + RevertingERC1155Recipient to = new RevertingERC1155Recipient(); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + token.batchMint(address(to), ids, ""); + } + + function testFailBatchMintToWrongReturnDataERC1155Recipient() public { + WrongReturnDataERC1155BRecipient to = new WrongReturnDataERC1155BRecipient(); + + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + token.batchMint(address(to), ids, ""); + } + + function testFailBatchBurnInsufficientBalance() public { + uint256[] memory ids = new uint256[](5); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + ids[4] = 1341; + + token.batchBurn(address(0xBEEF), ids); + } + + function testFailBalanceOfBatchWithArrayMismatch() public view { + address[] memory tos = new address[](5); + tos[0] = address(0xBEEF); + tos[1] = address(0xCAFE); + tos[2] = address(0xFACE); + tos[3] = address(0xDEAD); + tos[4] = address(0xFEED); + + uint256[] memory ids = new uint256[](4); + ids[0] = 1337; + ids[1] = 1338; + ids[2] = 1339; + ids[3] = 1340; + + token.balanceOfBatch(tos, ids); + } + + // function testMintToEOA( + // address to, + // uint256 id, + // uint256 amount, + // bytes memory mintData + // ) public { + // if (to == address(0)) to = address(0xBEEF); + + // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; + + // token.mint(to, id, amount, mintData); + + // assertEq(token.balanceOf(to, id), amount); + // } + + // function testMintToERC1155Recipient( + // uint256 id, + // uint256 amount, + // bytes memory mintData + // ) public { + // ERC1155BRecipient to = new ERC1155BRecipient(); + + // token.mint(address(to), id, amount, mintData); + + // assertEq(token.balanceOf(address(to), id), amount); + + // assertEq(to.operator(), address(this)); + // assertEq(to.from(), address(0)); + // assertEq(to.id(), id); + // assertBytesEq(to.mintData(), mintData); + // } + + // function testBatchMintToEOA( + // address to, + // uint256[] memory ids, + // uint256[] memory amounts, + // bytes memory mintData + // ) public { + // if (to == address(0)) to = address(0xBEEF); + + // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; + + // uint256 minLength = min2(ids.length, amounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[to][id]; + + // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); + + // normalizedIds[i] = id; + // normalizedAmounts[i] = mintAmount; + + // userMintAmounts[to][id] += mintAmount; + // } + + // token.batchMint(to, normalizedIds, normalizedAmounts, mintData); + + // for (uint256 i = 0; i < normalizedIds.length; i++) { + // uint256 id = normalizedIds[i]; + + // assertEq(token.balanceOf(to, id), userMintAmounts[to][id]); + // } + // } + + // function testBatchMintToERC1155Recipient( + // uint256[] memory ids, + // uint256[] memory amounts, + // bytes memory mintData + // ) public { + // ERC1155BRecipient to = new ERC1155BRecipient(); + + // uint256 minLength = min2(ids.length, amounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; + + // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); + + // normalizedIds[i] = id; + // normalizedAmounts[i] = mintAmount; + + // userMintAmounts[address(to)][id] += mintAmount; + // } + + // token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); + + // assertEq(to.batchOperator(), address(this)); + // assertEq(to.batchFrom(), address(0)); + // assertUintArrayEq(to.batchIds(), normalizedIds); + // assertUintArrayEq(to.batchAmounts(), normalizedAmounts); + // assertBytesEq(to.batchData(), mintData); + + // for (uint256 i = 0; i < normalizedIds.length; i++) { + // uint256 id = normalizedIds[i]; + + // assertEq(token.balanceOf(address(to), id), userMintAmounts[address(to)][id]); + // } + // } + + // function testBurn( + // address to, + // uint256 id, + // uint256 mintAmount, + // bytes memory mintData, + // uint256 burnAmount + // ) public { + // if (to == address(0)) to = address(0xBEEF); + + // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; + + // burnAmount = bound(burnAmount, 0, mintAmount); + + // token.mint(to, id, mintAmount, mintData); + + // token.burn(to, id, burnAmount); + + // assertEq(token.balanceOf(address(to), id), mintAmount - burnAmount); + // } + + // function testBatchBurn( + // address to, + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory burnAmounts, + // bytes memory mintData + // ) public { + // if (to == address(0)) to = address(0xBEEF); + + // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; + + // uint256 minLength = min3(ids.length, mintAmounts.length, burnAmounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedBurnAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = bound(mintAmounts[i], 0, remainingMintAmountForId); + // normalizedBurnAmounts[i] = bound(burnAmounts[i], 0, normalizedMintAmounts[i]); + + // userMintAmounts[address(to)][id] += normalizedMintAmounts[i]; + // userTransferOrBurnAmounts[address(to)][id] += normalizedBurnAmounts[i]; + // } + + // token.batchMint(to, normalizedIds, normalizedMintAmounts, mintData); + + // token.batchBurn(to, normalizedIds, normalizedBurnAmounts); + + // for (uint256 i = 0; i < normalizedIds.length; i++) { + // uint256 id = normalizedIds[i]; + + // assertEq(token.balanceOf(to, id), userMintAmounts[to][id] - userTransferOrBurnAmounts[to][id]); + // } + // } + + // function testApproveAll(address to, bool approved) public { + // token.setApprovalForAll(to, approved); + + // assertBoolEq(token.isApprovedForAll(address(this), to), approved); + // } + + // function testSafeTransferFromToEOA( + // uint256 id, + // uint256 mintAmount, + // bytes memory mintData, + // uint256 transferAmount, + // address to, + // bytes memory transferData + // ) public { + // if (to == address(0)) to = address(0xBEEF); + + // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; + + // transferAmount = bound(transferAmount, 0, mintAmount); + + // ERC1155BUser from = new ERC1155BUser(token); + + // token.mint(address(from), id, mintAmount, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeTransferFrom(address(from), to, id, transferAmount, transferData); + + // assertEq(token.balanceOf(to, id), transferAmount); + // assertEq(token.balanceOf(address(from), id), mintAmount - transferAmount); + // } + + // function testSafeTransferFromToERC1155Recipient( + // uint256 id, + // uint256 mintAmount, + // bytes memory mintData, + // uint256 transferAmount, + // bytes memory transferData + // ) public { + // ERC1155BRecipient to = new ERC1155BRecipient(); + + // ERC1155BUser from = new ERC1155BUser(token); + + // transferAmount = bound(transferAmount, 0, mintAmount); + + // token.mint(address(from), id, mintAmount, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeTransferFrom(address(from), address(to), id, transferAmount, transferData); + + // assertEq(to.operator(), address(this)); + // assertEq(to.from(), address(from)); + // assertEq(to.id(), id); + // assertBytesEq(to.mintData(), transferData); + + // assertEq(token.balanceOf(address(to), id), transferAmount); + // assertEq(token.balanceOf(address(from), id), mintAmount - transferAmount); + // } + + // function testSafeTransferFromSelf( + // uint256 id, + // uint256 mintAmount, + // bytes memory mintData, + // uint256 transferAmount, + // address to, + // bytes memory transferData + // ) public { + // if (to == address(0)) to = address(0xBEEF); + + // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; + + // transferAmount = bound(transferAmount, 0, mintAmount); + + // token.mint(address(this), id, mintAmount, mintData); + + // token.safeTransferFrom(address(this), to, id, transferAmount, transferData); + + // assertEq(token.balanceOf(to, id), transferAmount); + // assertEq(token.balanceOf(address(this), id), mintAmount - transferAmount); + // } + + // function testSafeBatchTransferFromToEOA( + // address to, + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory transferAmounts, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // if (to == address(0)) to = address(0xBEEF); + + // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; + + // ERC1155BUser from = new ERC1155BUser(token); + + // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; + + // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); + // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = mintAmount; + // normalizedTransferAmounts[i] = transferAmount; + + // userMintAmounts[address(from)][id] += mintAmount; + // userTransferOrBurnAmounts[address(from)][id] += transferAmount; + // } + + // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeBatchTransferFrom(address(from), to, normalizedIds, normalizedTransferAmounts, transferData); + + // for (uint256 i = 0; i < normalizedIds.length; i++) { + // uint256 id = normalizedIds[i]; + + // assertEq(token.balanceOf(address(to), id), userTransferOrBurnAmounts[address(from)][id]); + // assertEq( + // token.balanceOf(address(from), id), + // userMintAmounts[address(from)][id] - userTransferOrBurnAmounts[address(from)][id] + // ); + // } + // } + + // function testSafeBatchTransferFromToERC1155Recipient( + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory transferAmounts, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // ERC1155BUser from = new ERC1155BUser(token); + + // ERC1155BRecipient to = new ERC1155BRecipient(); + + // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; + + // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); + // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = mintAmount; + // normalizedTransferAmounts[i] = transferAmount; + + // userMintAmounts[address(from)][id] += mintAmount; + // userTransferOrBurnAmounts[address(from)][id] += transferAmount; + // } + + // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeBatchTransferFrom(address(from), address(to), normalizedIds, normalizedTransferAmounts, transferData); + + // assertEq(to.batchOperator(), address(this)); + // assertEq(to.batchFrom(), address(from)); + // assertUintArrayEq(to.batchIds(), normalizedIds); + // assertUintArrayEq(to.batchAmounts(), normalizedTransferAmounts); + // assertBytesEq(to.batchData(), transferData); + + // for (uint256 i = 0; i < normalizedIds.length; i++) { + // uint256 id = normalizedIds[i]; + // uint256 transferAmount = userTransferOrBurnAmounts[address(from)][id]; + + // assertEq(token.balanceOf(address(to), id), transferAmount); + // assertEq(token.balanceOf(address(from), id), userMintAmounts[address(from)][id] - transferAmount); + // } + // } + + // function testBatchBalanceOf( + // address[] memory tos, + // uint256[] memory ids, + // uint256[] memory amounts, + // bytes memory mintData + // ) public { + // uint256 minLength = min3(tos.length, ids.length, amounts.length); + + // address[] memory normalizedTos = new address[](minLength); + // uint256[] memory normalizedIds = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + // address to = tos[i] == address(0) ? address(0xBEEF) : tos[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[to][id]; + + // normalizedTos[i] = to; + // normalizedIds[i] = id; + + // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); + + // token.mint(to, id, mintAmount, mintData); + + // userMintAmounts[to][id] += mintAmount; + // } + + // uint256[] memory balances = token.balanceOfBatch(normalizedTos, normalizedIds); + + // for (uint256 i = 0; i < normalizedTos.length; i++) { + // assertEq(balances[i], token.balanceOf(normalizedTos[i], normalizedIds[i])); + // } + // } + + // function testFailMintToZero( + // uint256 id, + // uint256 amount, + // bytes memory data + // ) public { + // token.mint(address(0), id, amount, data); + // } + + // function testFailMintToNonERC1155Recipient( + // uint256 id, + // uint256 mintAmount, + // bytes memory mintData + // ) public { + // token.mint(address(new NonERC1155BRecipient()), id, mintAmount, mintData); + // } + + // function testFailMintToRevertingERC1155Recipient( + // uint256 id, + // uint256 mintAmount, + // bytes memory mintData + // ) public { + // token.mint(address(new RevertingERC1155Recipient()), id, mintAmount, mintData); + // } + + // function testFailMintToWrongReturnDataERC1155Recipient( + // uint256 id, + // uint256 mintAmount, + // bytes memory mintData + // ) public { + // token.mint(address(new RevertingERC1155Recipient()), id, mintAmount, mintData); + // } + + // function testFailBurnInsufficientBalance( + // address to, + // uint256 id, + // uint256 mintAmount, + // uint256 burnAmount, + // bytes memory mintData + // ) public { + // burnAmount = bound(burnAmount, mintAmount + 1, type(uint256).max); + + // token.mint(to, id, mintAmount, mintData); + // token.burn(to, id, burnAmount); + // } + + // function testFailSafeTransferFromInsufficientBalance( + // address to, + // uint256 id, + // uint256 mintAmount, + // uint256 transferAmount, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // ERC1155BUser from = new ERC1155BUser(token); + + // transferAmount = bound(transferAmount, mintAmount + 1, type(uint256).max); + + // token.mint(address(from), id, mintAmount, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeTransferFrom(address(from), to, id, transferAmount, transferData); + // } + + // function testFailSafeTransferFromSelfInsufficientBalance( + // address to, + // uint256 id, + // uint256 mintAmount, + // uint256 transferAmount, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // transferAmount = bound(transferAmount, mintAmount + 1, type(uint256).max); + + // token.mint(address(this), id, mintAmount, mintData); + // token.safeTransferFrom(address(this), to, id, transferAmount, transferData); + // } + + // function testFailSafeTransferFromToZero( + // uint256 id, + // uint256 mintAmount, + // uint256 transferAmount, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // transferAmount = bound(transferAmount, 0, mintAmount); + + // token.mint(address(this), id, mintAmount, mintData); + // token.safeTransferFrom(address(this), address(0), id, transferAmount, transferData); + // } + + // function testFailSafeTransferFromToNonERC1155Recipient( + // uint256 id, + // uint256 mintAmount, + // uint256 transferAmount, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // transferAmount = bound(transferAmount, 0, mintAmount); + + // token.mint(address(this), id, mintAmount, mintData); + // token.safeTransferFrom(address(this), address(new NonERC1155BRecipient()), id, transferAmount, transferData); + // } + + // function testFailSafeTransferFromToRevertingERC1155Recipient( + // uint256 id, + // uint256 mintAmount, + // uint256 transferAmount, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // transferAmount = bound(transferAmount, 0, mintAmount); + + // token.mint(address(this), id, mintAmount, mintData); + // token.safeTransferFrom( + // address(this), + // address(new RevertingERC1155Recipient()), + // id, + // transferAmount, + // transferData + // ); + // } + + // function testFailSafeTransferFromToWrongReturnDataERC1155Recipient( + // uint256 id, + // uint256 mintAmount, + // uint256 transferAmount, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // transferAmount = bound(transferAmount, 0, mintAmount); + + // token.mint(address(this), id, mintAmount, mintData); + // token.safeTransferFrom( + // address(this), + // address(new WrongReturnDataERC1155BRecipient()), + // id, + // transferAmount, + // transferData + // ); + // } + + // function testFailSafeBatchTransferInsufficientBalance( + // address to, + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory transferAmounts, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // ERC1155BUser from = new ERC1155BUser(token); + + // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); + + // if (minLength == 0) revert(); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; + + // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); + // uint256 transferAmount = bound(transferAmounts[i], mintAmount + 1, type(uint256).max); + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = mintAmount; + // normalizedTransferAmounts[i] = transferAmount; + + // userMintAmounts[address(from)][id] += mintAmount; + // } + + // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeBatchTransferFrom(address(from), to, normalizedIds, normalizedTransferAmounts, transferData); + // } + + // function testFailSafeBatchTransferFromToZero( + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory transferAmounts, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // ERC1155BUser from = new ERC1155BUser(token); + + // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; + + // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); + // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = mintAmount; + // normalizedTransferAmounts[i] = transferAmount; + + // userMintAmounts[address(from)][id] += mintAmount; + // } + + // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeBatchTransferFrom(address(from), address(0), normalizedIds, normalizedTransferAmounts, transferData); + // } + + // function testFailSafeBatchTransferFromToNonERC1155Recipient( + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory transferAmounts, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // ERC1155BUser from = new ERC1155BUser(token); + + // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; + + // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); + // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = mintAmount; + // normalizedTransferAmounts[i] = transferAmount; + + // userMintAmounts[address(from)][id] += mintAmount; + // } + + // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeBatchTransferFrom( + // address(from), + // address(new NonERC1155BRecipient()), + // normalizedIds, + // normalizedTransferAmounts, + // transferData + // ); + // } + + // function testFailSafeBatchTransferFromToRevertingERC1155Recipient( + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory transferAmounts, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // ERC1155BUser from = new ERC1155BUser(token); + + // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; + + // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); + // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = mintAmount; + // normalizedTransferAmounts[i] = transferAmount; + + // userMintAmounts[address(from)][id] += mintAmount; + // } + + // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeBatchTransferFrom( + // address(from), + // address(new RevertingERC1155Recipient()), + // normalizedIds, + // normalizedTransferAmounts, + // transferData + // ); + // } + + // function testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient( + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory transferAmounts, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // ERC1155BUser from = new ERC1155BUser(token); + + // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; + + // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); + // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = mintAmount; + // normalizedTransferAmounts[i] = transferAmount; + + // userMintAmounts[address(from)][id] += mintAmount; + // } + + // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeBatchTransferFrom( + // address(from), + // address(new WrongReturnDataERC1155BRecipient()), + // normalizedIds, + // normalizedTransferAmounts, + // transferData + // ); + // } + + // function testFailSafeBatchTransferFromWithArrayLengthMismatch( + // address to, + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory transferAmounts, + // bytes memory mintData, + // bytes memory transferData + // ) public { + // ERC1155BUser from = new ERC1155BUser(token); + + // if (ids.length == transferAmounts.length) revert(); + + // token.batchMint(address(from), ids, mintAmounts, mintData); + + // from.setApprovalForAll(address(this), true); + + // token.safeBatchTransferFrom(address(from), to, ids, transferAmounts, transferData); + // } + + // function testFailBatchMintToZero( + // uint256[] memory ids, + // uint256[] memory amounts, + // bytes memory mintData + // ) public { + // uint256 minLength = min2(ids.length, amounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(0)][id]; + + // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); + + // normalizedIds[i] = id; + // normalizedAmounts[i] = mintAmount; + + // userMintAmounts[address(0)][id] += mintAmount; + // } + + // token.batchMint(address(0), normalizedIds, normalizedAmounts, mintData); + // } + + // function testFailBatchMintToNonERC1155Recipient( + // uint256[] memory ids, + // uint256[] memory amounts, + // bytes memory mintData + // ) public { + // NonERC1155BRecipient to = new NonERC1155BRecipient(); + + // uint256 minLength = min2(ids.length, amounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; + + // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); + + // normalizedIds[i] = id; + // normalizedAmounts[i] = mintAmount; + + // userMintAmounts[address(to)][id] += mintAmount; + // } + + // token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); + // } + + // function testFailBatchMintToRevertingERC1155Recipient( + // uint256[] memory ids, + // uint256[] memory amounts, + // bytes memory mintData + // ) public { + // RevertingERC1155Recipient to = new RevertingERC1155Recipient(); + + // uint256 minLength = min2(ids.length, amounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; + + // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); + + // normalizedIds[i] = id; + // normalizedAmounts[i] = mintAmount; + + // userMintAmounts[address(to)][id] += mintAmount; + // } + + // token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); + // } + + // function testFailBatchMintToWrongReturnDataERC1155Recipient( + // uint256[] memory ids, + // uint256[] memory amounts, + // bytes memory mintData + // ) public { + // WrongReturnDataERC1155BRecipient to = new WrongReturnDataERC1155BRecipient(); + + // uint256 minLength = min2(ids.length, amounts.length); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; + + // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); + + // normalizedIds[i] = id; + // normalizedAmounts[i] = mintAmount; + + // userMintAmounts[address(to)][id] += mintAmount; + // } + + // token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); + // } + + // function testFailBatchMintWithArrayMismatch( + // address to, + // uint256[] memory ids, + // uint256[] memory amounts, + // bytes memory mintData + // ) public { + // if (ids.length == amounts.length) revert(); + + // token.batchMint(address(to), ids, amounts, mintData); + // } + + // function testFailBatchBurnInsufficientBalance( + // address to, + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory burnAmounts, + // bytes memory mintData + // ) public { + // uint256 minLength = min3(ids.length, mintAmounts.length, burnAmounts.length); + + // if (minLength == 0) revert(); + + // uint256[] memory normalizedIds = new uint256[](minLength); + // uint256[] memory normalizedMintAmounts = new uint256[](minLength); + // uint256[] memory normalizedBurnAmounts = new uint256[](minLength); + + // for (uint256 i = 0; i < minLength; i++) { + // uint256 id = ids[i]; + + // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[to][id]; + + // normalizedIds[i] = id; + // normalizedMintAmounts[i] = bound(mintAmounts[i], 0, remainingMintAmountForId); + // normalizedBurnAmounts[i] = bound(burnAmounts[i], normalizedMintAmounts[i] + 1, type(uint256).max); + + // userMintAmounts[to][id] += normalizedMintAmounts[i]; + // } + + // token.batchMint(to, normalizedIds, normalizedMintAmounts, mintData); + + // token.batchBurn(to, normalizedIds, normalizedBurnAmounts); + // } + + // function testFailBatchBurnWithArrayLengthMismatch( + // address to, + // uint256[] memory ids, + // uint256[] memory mintAmounts, + // uint256[] memory burnAmounts, + // bytes memory mintData + // ) public { + // if (ids.length == burnAmounts.length) revert(); + + // token.batchMint(to, ids, mintAmounts, mintData); + + // token.batchBurn(to, ids, burnAmounts); + // } + + // function testFailBalanceOfBatchWithArrayMismatch(address[] memory tos, uint256[] memory ids) public view { + // if (tos.length == ids.length) revert(); + + // token.balanceOfBatch(tos, ids); + // } +} diff --git a/src/test/utils/mocks/MockERC1155B.sol b/src/test/utils/mocks/MockERC1155B.sol new file mode 100644 index 00000000..f263f3f5 --- /dev/null +++ b/src/test/utils/mocks/MockERC1155B.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +import {ERC1155B} from "../../../tokens/ERC1155B.sol"; + +contract MockERC1155B is ERC1155B { + function uri(uint256) public pure virtual override returns (string memory) {} + + function mint( + address to, + uint256 id, + bytes memory data + ) public virtual { + _mint(to, id, data); + } + + function batchMint( + address to, + uint256[] memory ids, + bytes memory data + ) public virtual { + _batchMint(to, ids, data); + } + + function burn(uint256 id) public virtual { + _burn(id); + } + + function batchBurn(address from, uint256[] memory ids) public virtual { + _batchBurn(from, ids); + } +} diff --git a/src/test/utils/users/ERC1155BUser.sol b/src/test/utils/users/ERC1155BUser.sol new file mode 100644 index 00000000..68c680ce --- /dev/null +++ b/src/test/utils/users/ERC1155BUser.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +import {ERC1155TokenReceiver} from "../../../tokens/ERC1155.sol"; +import {ERC1155B} from "../../../tokens/ERC1155B.sol"; + +contract ERC1155BUser is ERC1155TokenReceiver { + ERC1155B token; + + constructor(ERC1155B _token) { + token = _token; + } + + function onERC1155Received( + address, + address, + uint256, + uint256, + bytes calldata + ) external virtual override returns (bytes4) { + return ERC1155TokenReceiver.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external virtual override returns (bytes4) { + return ERC1155TokenReceiver.onERC1155BatchReceived.selector; + } + + function setApprovalForAll(address operator, bool approved) public virtual { + token.setApprovalForAll(operator, approved); + } + + function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes memory data + ) public virtual { + token.safeTransferFrom(from, to, id, amount, data); + } + + function safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data + ) public virtual { + token.safeBatchTransferFrom(from, to, ids, amounts, data); + } +} diff --git a/src/tokens/ERC1155B.sol b/src/tokens/ERC1155B.sol new file mode 100644 index 00000000..6e407da8 --- /dev/null +++ b/src/tokens/ERC1155B.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +import {ERC1155TokenReceiver} from "./ERC1155.sol"; + +/// @notice Minimalist and gas efficient ERC1155 implementation optimized for single supply ids. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155B.sol) +abstract contract ERC1155B { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event TransferSingle( + address indexed operator, + address indexed from, + address indexed to, + uint256 id, + uint256 amount + ); + + event TransferBatch( + address indexed operator, + address indexed from, + address indexed to, + uint256[] ids, + uint256[] amounts + ); + + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); + + event URI(string value, uint256 indexed id); + + /*////////////////////////////////////////////////////////////// + ERC1155 STORAGE + //////////////////////////////////////////////////////////////*/ + + mapping(address => mapping(address => bool)) public isApprovedForAll; + + /*////////////////////////////////////////////////////////////// + ERC1155B STORAGE + //////////////////////////////////////////////////////////////*/ + + mapping(uint256 => address) public ownerOf; + + function balanceOf(address owner, uint256 id) public view virtual returns (uint256 bal) { + address idOwner = ownerOf[id]; + + assembly { + // We avoid branching by using assembly to take + // the bool output of eq() and use it as a uint. + bal := eq(idOwner, owner) + } + } + + /*////////////////////////////////////////////////////////////// + METADATA LOGIC + //////////////////////////////////////////////////////////////*/ + + function uri(uint256 id) public view virtual returns (string memory); + + /*////////////////////////////////////////////////////////////// + ERC1155 LOGIC + //////////////////////////////////////////////////////////////*/ + + function setApprovalForAll(address operator, bool approved) public virtual { + isApprovedForAll[msg.sender][operator] = approved; + + emit ApprovalForAll(msg.sender, operator, approved); + } + + function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes calldata data + ) public virtual { + require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); + + require(from == ownerOf[id], "WRONG_FROM"); // Can only transfer from the owner. + + // Can only transfer 1 with ERC1155B. + require(amount == 1, "INVALID_AMOUNT"); + + ownerOf[id] = to; + + emit TransferSingle(msg.sender, from, to, id, amount); + + require( + to.code.length == 0 + ? to != address(0) + : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == + ERC1155TokenReceiver.onERC1155Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + function safeBatchTransferFrom( + address from, + address to, + uint256[] calldata ids, + uint256[] calldata amounts, + bytes calldata data + ) public virtual { + require(ids.length == amounts.length, "LENGTH_MISMATCH"); + + require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); + + // Storing these outside the loop saves ~15 gas per iteration. + uint256 id; + uint256 amount; + + // Unchecked because the only math done is incrementing + // the array index counter which cannot possibly overflow. + unchecked { + for (uint256 i = 0; i < ids.length; i++) { + id = ids[i]; + amount = amounts[i]; + + // Can only transfer from the owner. + require(from == ownerOf[id], "WRONG_FROM"); + + // Can only transfer 1 with ERC1155B. + require(amount == 1, "INVALID_AMOUNT"); + + ownerOf[id] = to; + } + } + + emit TransferBatch(msg.sender, from, to, ids, amounts); + + require( + to.code.length == 0 + ? to != address(0) + : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == + ERC1155TokenReceiver.onERC1155BatchReceived.selector, + "UNSAFE_RECIPIENT" + ); + } + + function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) + public + view + virtual + returns (uint256[] memory balances) + { + require(owners.length == ids.length, "LENGTH_MISMATCH"); + + balances = new uint256[](owners.length); + + // Unchecked because the only math done is incrementing + // the array index counter which cannot possibly overflow. + unchecked { + for (uint256 i = 0; i < owners.length; ++i) { + balances[i] = balanceOf(owners[i], ids[i]); + } + } + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint( + address to, + uint256 id, + bytes memory data + ) internal virtual { + // Minting twice would effectively be a force transfer. + require(ownerOf[id] == address(0), "ALREADY_MINTED"); + + ownerOf[id] = to; + + emit TransferSingle(msg.sender, address(0), to, id, 1); + + require( + to.code.length == 0 + ? to != address(0) + : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, 1, data) == + ERC1155TokenReceiver.onERC1155Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + function _batchMint( + address to, + uint256[] memory ids, + bytes memory data + ) internal virtual { + uint256 idsLength = ids.length; // Saves MLOADs. + + // Generate an amounts array locally to use in the event below. + uint256[] memory amounts = new uint256[](idsLength); + + uint256 id; // Storing outside the loop saves ~7 gas per iteration. + + // Unchecked because the only math done is incrementing + // the array index counter which cannot possibly overflow. + unchecked { + for (uint256 i = 0; i < idsLength; ++i) { + id = ids[i]; + + // Minting twice would effectively be a force transfer. + require(ownerOf[id] == address(0), "ALREADY_MINTED"); + + ownerOf[id] = to; + + amounts[i] = 1; + } + } + + emit TransferBatch(msg.sender, address(0), to, ids, amounts); + + require( + to.code.length == 0 + ? to != address(0) + : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == + ERC1155TokenReceiver.onERC1155BatchReceived.selector, + "UNSAFE_RECIPIENT" + ); + } + + function _batchBurn(address from, uint256[] memory ids) internal virtual { + // Burning unminted tokens makes no sense. + require(from != address(0), "INVALID_FROM"); + + uint256 idsLength = ids.length; // Saves MLOADs. + + // Generate an amounts array locally to use in the event below. + uint256[] memory amounts = new uint256[](idsLength); + + uint256 id; // Storing outside the loop saves ~7 gas per iteration. + + // Unchecked because the only math done is incrementing + // the array index counter which cannot possibly overflow. + unchecked { + for (uint256 i = 0; i < idsLength; ++i) { + id = ids[i]; + + require(ownerOf[id] == from, "WRONG_FROM"); + + ownerOf[id] = address(0); + + amounts[i] = 1; + } + } + + emit TransferBatch(msg.sender, from, address(0), ids, amounts); + } + + function _burn(uint256 id) internal virtual { + address owner = ownerOf[id]; + + require(owner != address(0), "NOT_MINTED"); + + ownerOf[id] = address(0); + + emit TransferSingle(msg.sender, owner, address(0), id, 1); + } +} From d9211e93ec75dbf3fcda344ec758088544d71fc7 Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 12 May 2022 23:33:22 -0700 Subject: [PATCH 09/44] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Clobber=20reserved?= =?UTF-8?q?=20slots=20in=20STL=20(#204)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 334 +++++++++++++++++----------------- src/utils/SafeTransferLib.sol | 73 ++++---- 2 files changed, 207 insertions(+), 200 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 1a91e953..b0313e5a 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,18 +1,18 @@ -AuthTest:testCallFunctionAsOwner() (gas: 29871) -AuthTest:testCallFunctionWithPermissiveAuthority() (gas: 124249) +AuthTest:testCallFunctionAsOwner() (gas: 29828) +AuthTest:testCallFunctionWithPermissiveAuthority() (gas: 124270) AuthTest:testFailCallFunctionAsNonOwner() (gas: 15491) -AuthTest:testFailCallFunctionAsOwnerWithOutOfOrderAuthority() (gas: 136021) -AuthTest:testFailCallFunctionWithRestrictiveAuthority() (gas: 129201) -AuthTest:testFailSetAuthorityAsNonOwner() (gas: 18260) +AuthTest:testFailCallFunctionAsOwnerWithOutOfOrderAuthority() (gas: 136042) +AuthTest:testFailCallFunctionWithRestrictiveAuthority() (gas: 129178) +AuthTest:testFailSetAuthorityAsNonOwner() (gas: 18304) AuthTest:testFailSetAuthorityWithRestrictiveAuthority() (gas: 129078) -AuthTest:testFailSetOwnerAsNonOwner() (gas: 15609) -AuthTest:testFailSetOwnerAsOwnerWithOutOfOrderAuthority() (gas: 136161) -AuthTest:testFailSetOwnerWithRestrictiveAuthority() (gas: 129242) -AuthTest:testSetAuthorityAsOwner() (gas: 32302) -AuthTest:testSetAuthorityAsOwnerWithOutOfOrderAuthority() (gas: 226396) -AuthTest:testSetAuthorityWithPermissiveAuthority() (gas: 125963) -AuthTest:testSetOwnerAsOwner() (gas: 15298) -AuthTest:testSetOwnerWithPermissiveAuthority() (gas: 127884) +AuthTest:testFailSetOwnerAsNonOwner() (gas: 15587) +AuthTest:testFailSetOwnerAsOwnerWithOutOfOrderAuthority() (gas: 136118) +AuthTest:testFailSetOwnerWithRestrictiveAuthority() (gas: 129264) +AuthTest:testSetAuthorityAsOwner() (gas: 32235) +AuthTest:testSetAuthorityAsOwnerWithOutOfOrderAuthority() (gas: 226463) +AuthTest:testSetAuthorityWithPermissiveAuthority() (gas: 125918) +AuthTest:testSetOwnerAsOwner() (gas: 15276) +AuthTest:testSetOwnerWithPermissiveAuthority() (gas: 127906) Bytes32AddressLibTest:testFillLast12Bytes() (gas: 223) Bytes32AddressLibTest:testFromLast20Bytes() (gas: 191) CREATE3Test:testDeployERC20() (gas: 852410) @@ -20,46 +20,46 @@ CREATE3Test:testFailDoubleDeployDifferentBytecode() (gas: 9079256848778914164) CREATE3Test:testFailDoubleDeploySameBytecode() (gas: 9079256848778906218) DSTestPlusTest:testBound() (gas: 14208) DSTestPlusTest:testBrutalizeMemory() (gas: 823) -DSTestPlusTest:testFailBoundMinBiggerThanMax() (gas: 309) -DSTestPlusTest:testMeasuringGas() (gas: 24622) -DSTestPlusTest:testRelApproxEqBothZeroesPasses() (gas: 413) -ERC1155Test:testApproveAll() (gas: 31009) -ERC1155Test:testBatchBalanceOf() (gas: 157631) -ERC1155Test:testBatchBurn() (gas: 151074) -ERC1155Test:testBatchMintToEOA() (gas: 137337) -ERC1155Test:testBatchMintToERC1155Recipient() (gas: 942650) -ERC1155Test:testBurn() (gas: 38598) +DSTestPlusTest:testFailBoundMinBiggerThanMax() (gas: 287) +DSTestPlusTest:testMeasuringGas() (gas: 24600) +DSTestPlusTest:testRelApproxEqBothZeroesPasses() (gas: 391) +ERC1155Test:testApproveAll() (gas: 31053) +ERC1155Test:testBatchBalanceOf() (gas: 157587) +ERC1155Test:testBatchBurn() (gas: 151051) +ERC1155Test:testBatchMintToEOA() (gas: 137293) +ERC1155Test:testBatchMintToERC1155Recipient() (gas: 942660) +ERC1155Test:testBurn() (gas: 38576) ERC1155Test:testFailBalanceOfBatchWithArrayMismatch() (gas: 7933) -ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136156) -ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 135542) -ERC1155Test:testFailBatchMintToNonERC1155Recipient() (gas: 167292) -ERC1155Test:testFailBatchMintToRevertingERC1155Recipient() (gas: 358811) -ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 310743) -ERC1155Test:testFailBatchMintToZero() (gas: 131737) -ERC1155Test:testFailBatchMintWithArrayMismatch() (gas: 9600) -ERC1155Test:testFailBurnInsufficientBalance() (gas: 34852) -ERC1155Test:testFailMintToNonERC155Recipient() (gas: 68191) -ERC1155Test:testFailMintToRevertingERC155Recipient() (gas: 259435) -ERC1155Test:testFailMintToWrongReturnDataERC155Recipient() (gas: 259389) +ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136177) +ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 135543) +ERC1155Test:testFailBatchMintToNonERC1155Recipient() (gas: 167311) +ERC1155Test:testFailBatchMintToRevertingERC1155Recipient() (gas: 358854) +ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 310745) +ERC1155Test:testFailBatchMintToZero() (gas: 131716) +ERC1155Test:testFailBatchMintWithArrayMismatch() (gas: 9621) +ERC1155Test:testFailBurnInsufficientBalance() (gas: 34830) +ERC1155Test:testFailMintToNonERC155Recipient() (gas: 68192) +ERC1155Test:testFailMintToRevertingERC155Recipient() (gas: 259413) +ERC1155Test:testFailMintToWrongReturnDataERC155Recipient() (gas: 259412) ERC1155Test:testFailMintToZero() (gas: 33705) -ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 321377) -ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 512956) -ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 464847) -ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 286556) -ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 162674) -ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 163555) -ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 63245) -ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance() (gas: 34297) +ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 321355) +ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 512934) +ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 464869) +ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 286535) +ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 162653) +ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 163533) +ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 63267) +ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance() (gas: 34320) ERC1155Test:testFailSafeTransferFromToNonERC155Recipient() (gas: 96510) -ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 287731) -ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 239587) +ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 287732) +ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 239610) ERC1155Test:testFailSafeTransferFromToZero() (gas: 62014) -ERC1155Test:testMintToEOA() (gas: 34765) -ERC1155Test:testMintToERC1155Recipient() (gas: 608328) +ERC1155Test:testMintToEOA() (gas: 34743) +ERC1155Test:testMintToERC1155Recipient() (gas: 608327) ERC1155Test:testSafeBatchTransferFromToEOA() (gas: 297822) ERC1155Test:testSafeBatchTransferFromToERC1155Recipient() (gas: 1122274) -ERC1155Test:testSafeTransferFromSelf() (gas: 64177) -ERC1155Test:testSafeTransferFromToEOA() (gas: 93167) +ERC1155Test:testSafeTransferFromSelf() (gas: 64155) +ERC1155Test:testSafeTransferFromToEOA() (gas: 93168) ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 686500) ERC1155BTest:testApproveAll() (gas: 30947) ERC1155BTest:testBatchBalanceOf() (gas: 157240) @@ -97,160 +97,164 @@ ERC1155BTest:testSafeBatchTransferFromToERC1155Recipient() (gas: 1522381) ERC1155BTest:testSafeTransferFromSelf() (gas: 41780) ERC1155BTest:testSafeTransferFromToEOA() (gas: 582836) ERC1155BTest:testSafeTransferFromToERC1155Recipient() (gas: 1175937) -ERC20Test:testApprove() (gas: 31058) -ERC20Test:testBurn() (gas: 56970) +ERC20Test:testApprove() (gas: 31080) +ERC20Test:testBurn() (gas: 57014) ERC20Test:testFailPermitBadDeadline() (gas: 36924) ERC20Test:testFailPermitBadNonce() (gas: 36874) ERC20Test:testFailPermitPastDeadline() (gas: 10938) ERC20Test:testFailPermitReplay() (gas: 66285) -ERC20Test:testFailTransferFromInsufficientAllowance() (gas: 80882) -ERC20Test:testFailTransferFromInsufficientBalance() (gas: 81358) -ERC20Test:testFailTransferInsufficientBalance() (gas: 52806) -ERC20Test:testInfiniteApproveTransferFrom() (gas: 89793) -ERC20Test:testMint() (gas: 53746) -ERC20Test:testPermit() (gas: 63193) -ERC20Test:testTransfer() (gas: 60272) -ERC20Test:testTransferFrom() (gas: 83777) +ERC20Test:testFailTransferFromInsufficientAllowance() (gas: 80837) +ERC20Test:testFailTransferFromInsufficientBalance() (gas: 81336) +ERC20Test:testFailTransferInsufficientBalance() (gas: 52784) +ERC20Test:testInfiniteApproveTransferFrom() (gas: 89748) +ERC20Test:testMint() (gas: 53768) +ERC20Test:testPermit() (gas: 63237) +ERC20Test:testTransfer() (gas: 60228) +ERC20Test:testTransferFrom() (gas: 83821) ERC4626Test:testFailDepositWithNoApproval() (gas: 13345) ERC4626Test:testFailDepositWithNotEnoughApproval() (gas: 86963) -ERC4626Test:testFailDepositZero() (gas: 7768) -ERC4626Test:testFailMintWithNoApproval() (gas: 13290) +ERC4626Test:testFailDepositZero() (gas: 7790) +ERC4626Test:testFailMintWithNoApproval() (gas: 13246) ERC4626Test:testFailRedeemWithNoShareAmount() (gas: 32333) -ERC4626Test:testFailRedeemWithNotEnoughShareAmount() (gas: 203605) +ERC4626Test:testFailRedeemWithNotEnoughShareAmount() (gas: 203599) ERC4626Test:testFailRedeemZero() (gas: 7955) ERC4626Test:testFailWithdrawWithNoUnderlyingAmount() (gas: 32286) -ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203588) -ERC4626Test:testMintZero() (gas: 54526) -ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411114) -ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286088) -ERC4626Test:testWithdrawZero() (gas: 52393) +ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203539) +ERC4626Test:testMintZero() (gas: 54520) +ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411122) +ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286084) +ERC4626Test:testWithdrawZero() (gas: 52352) ERC721Test:testApprove() (gas: 78427) -ERC721Test:testApproveAll() (gas: 31063) -ERC721Test:testApproveBurn() (gas: 65550) -ERC721Test:testBurn() (gas: 46107) +ERC721Test:testApproveAll() (gas: 31086) +ERC721Test:testApproveBurn() (gas: 65584) +ERC721Test:testBurn() (gas: 46124) ERC721Test:testFailApproveUnAuthorized() (gas: 55598) -ERC721Test:testFailApproveUnMinted() (gas: 10236) -ERC721Test:testFailBalanceOfZeroAddress() (gas: 5555) +ERC721Test:testFailApproveUnMinted() (gas: 10194) +ERC721Test:testFailBalanceOfZeroAddress() (gas: 5576) ERC721Test:testFailBurnUnMinted() (gas: 7857) -ERC721Test:testFailDoubleBurn() (gas: 58943) +ERC721Test:testFailDoubleBurn() (gas: 58986) ERC721Test:testFailDoubleMint() (gas: 53286) -ERC721Test:testFailMintToZero() (gas: 5753) -ERC721Test:testFailOwnerOfUnminted() (gas: 7609) -ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnData() (gas: 159070) +ERC721Test:testFailMintToZero() (gas: 5754) +ERC721Test:testFailOwnerOfUnminted() (gas: 7631) +ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnData() (gas: 159028) ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnDataWithData() (gas: 159825) -ERC721Test:testFailSafeMintToNonERC721Recipient() (gas: 89205) +ERC721Test:testFailSafeMintToNonERC721Recipient() (gas: 89204) ERC721Test:testFailSafeMintToNonERC721RecipientWithData() (gas: 89990) ERC721Test:testFailSafeMintToRevertingERC721Recipient() (gas: 204738) -ERC721Test:testFailSafeMintToRevertingERC721RecipientWithData() (gas: 205512) -ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnData() (gas: 187270) +ERC721Test:testFailSafeMintToRevertingERC721RecipientWithData() (gas: 205556) +ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnData() (gas: 187272) ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData() (gas: 187722) -ERC721Test:testFailSafeTransferFromToNonERC721Recipient() (gas: 117408) -ERC721Test:testFailSafeTransferFromToNonERC721RecipientWithData() (gas: 117867) -ERC721Test:testFailSafeTransferFromToRevertingERC721Recipient() (gas: 233004) +ERC721Test:testFailSafeTransferFromToNonERC721Recipient() (gas: 117409) +ERC721Test:testFailSafeTransferFromToNonERC721RecipientWithData() (gas: 117889) +ERC721Test:testFailSafeTransferFromToRevertingERC721Recipient() (gas: 232982) ERC721Test:testFailSafeTransferFromToRevertingERC721RecipientWithData() (gas: 233391) -ERC721Test:testFailTransferFromNotOwner() (gas: 57872) -ERC721Test:testFailTransferFromToZero() (gas: 53381) -ERC721Test:testFailTransferFromUnOwned() (gas: 8000) -ERC721Test:testFailTransferFromWrongFrom() (gas: 53361) -ERC721Test:testMint() (gas: 54336) -ERC721Test:testSafeMintToEOA() (gas: 56976) -ERC721Test:testSafeMintToERC721Recipient() (gas: 381731) -ERC721Test:testSafeMintToERC721RecipientWithData() (gas: 402875) -ERC721Test:testSafeTransferFromToEOA() (gas: 95649) -ERC721Test:testSafeTransferFromToERC721Recipient() (gas: 440245) -ERC721Test:testSafeTransferFromToERC721RecipientWithData() (gas: 461043) +ERC721Test:testFailTransferFromNotOwner() (gas: 57894) +ERC721Test:testFailTransferFromToZero() (gas: 53359) +ERC721Test:testFailTransferFromUnOwned() (gas: 7999) +ERC721Test:testFailTransferFromWrongFrom() (gas: 53382) +ERC721Test:testMint() (gas: 54360) +ERC721Test:testSafeMintToEOA() (gas: 56974) +ERC721Test:testSafeMintToERC721Recipient() (gas: 381730) +ERC721Test:testSafeMintToERC721RecipientWithData() (gas: 402853) +ERC721Test:testSafeTransferFromToEOA() (gas: 95627) +ERC721Test:testSafeTransferFromToERC721Recipient() (gas: 440223) +ERC721Test:testSafeTransferFromToERC721RecipientWithData() (gas: 461042) ERC721Test:testTransferFrom() (gas: 86347) -ERC721Test:testTransferFromApproveAll() (gas: 92898) -ERC721Test:testTransferFromSelf() (gas: 64776) -FixedPointMathLibTest:testDivWadDown() (gas: 864) -FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 423) -FixedPointMathLibTest:testDivWadUp() (gas: 981) -FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 482) -FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 362) -FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 342) +ERC721Test:testTransferFromApproveAll() (gas: 92897) +ERC721Test:testTransferFromSelf() (gas: 64820) +FixedPointMathLibTest:testDivWadDown() (gas: 831) +FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 412) +FixedPointMathLibTest:testDivWadUp() (gas: 927) +FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 494) +FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 308) +FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 353) FixedPointMathLibTest:testFailMulDivDownZeroDenominator() (gas: 316) -FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 317) -FixedPointMathLibTest:testMulDivDown() (gas: 1861) -FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 751) -FixedPointMathLibTest:testMulDivUp() (gas: 2273) -FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 846) +FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 339) +FixedPointMathLibTest:testMulDivDown() (gas: 1905) +FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 729) +FixedPointMathLibTest:testMulDivUp() (gas: 2272) +FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 824) FixedPointMathLibTest:testMulWadDown() (gas: 821) -FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 886) -FixedPointMathLibTest:testMulWadUp() (gas: 959) -FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 1002) +FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 865) +FixedPointMathLibTest:testMulWadUp() (gas: 980) +FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 958) FixedPointMathLibTest:testRPow() (gas: 2142) FixedPointMathLibTest:testSqrt() (gas: 2156) -MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34292) -MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80556) +MerkleProofTest:testValidProofSupplied() (gas: 991) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 392) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 389) +MerkleProofTest:testVerifyInvalidProofSupplied() (gas: 977) +MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34293) +MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80575) MultiRolesAuthorityTest:testCanCallWithCustomAuthority() (gas: 422681) -MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesPublicCapability() (gas: 247674) -MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesUserWithRole() (gas: 256845) +MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesPublicCapability() (gas: 247696) +MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesUserWithRole() (gas: 256828) MultiRolesAuthorityTest:testSetPublicCapabilities() (gas: 27762) -MultiRolesAuthorityTest:testSetRoleCapabilities() (gas: 28985) -MultiRolesAuthorityTest:testSetRoles() (gas: 29006) +MultiRolesAuthorityTest:testSetRoleCapabilities() (gas: 28968) +MultiRolesAuthorityTest:testSetRoles() (gas: 28971) MultiRolesAuthorityTest:testSetTargetCustomAuthority() (gas: 27976) ReentrancyGuardTest:testFailUnprotectedCall() (gas: 45665) ReentrancyGuardTest:testNoReentrancy() (gas: 7515) ReentrancyGuardTest:testProtectedCall() (gas: 32949) -RolesAuthorityTest:testCanCallPublicCapability() (gas: 33336) -RolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 79601) +RolesAuthorityTest:testCanCallPublicCapability() (gas: 33319) +RolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 79584) RolesAuthorityTest:testSetPublicCapabilities() (gas: 29183) -RolesAuthorityTest:testSetRoleCapabilities() (gas: 30258) -RolesAuthorityTest:testSetRoles() (gas: 28986) -SSTORE2Test:testFailReadInvalidPointer() (gas: 2927) -SSTORE2Test:testFailReadInvalidPointerCustomBounds() (gas: 3099) +RolesAuthorityTest:testSetRoleCapabilities() (gas: 30276) +RolesAuthorityTest:testSetRoles() (gas: 28951) +SSTORE2Test:testFailReadInvalidPointer() (gas: 2905) +SSTORE2Test:testFailReadInvalidPointerCustomBounds() (gas: 3098) SSTORE2Test:testFailReadInvalidPointerCustomStartBound() (gas: 3004) -SSTORE2Test:testFailWriteReadEmptyOutOfBounds() (gas: 34470) +SSTORE2Test:testFailWriteReadEmptyOutOfBounds() (gas: 34448) SSTORE2Test:testFailWriteReadOutOfBounds() (gas: 34426) -SSTORE2Test:testFailWriteReadOutOfStartBound() (gas: 34362) +SSTORE2Test:testFailWriteReadOutOfStartBound() (gas: 34317) SSTORE2Test:testWriteRead() (gas: 53497) SSTORE2Test:testWriteReadCustomBounds() (gas: 34869) -SSTORE2Test:testWriteReadCustomStartBound() (gas: 34740) +SSTORE2Test:testWriteReadCustomStartBound() (gas: 34784) SSTORE2Test:testWriteReadEmptyBound() (gas: 34677) -SSTORE2Test:testWriteReadFullBoundedRead() (gas: 53672) +SSTORE2Test:testWriteReadFullBoundedRead() (gas: 53716) SSTORE2Test:testWriteReadFullStartBound() (gas: 34764) -SafeCastLibTest:testFailSafeCastTo128() (gas: 321) -SafeCastLibTest:testFailSafeCastTo160() (gas: 342) +SafeCastLibTest:testFailSafeCastTo128() (gas: 364) +SafeCastLibTest:testFailSafeCastTo160() (gas: 320) SafeCastLibTest:testFailSafeCastTo192() (gas: 344) -SafeCastLibTest:testFailSafeCastTo224() (gas: 343) -SafeCastLibTest:testFailSafeCastTo248() (gas: 365) -SafeCastLibTest:testFailSafeCastTo32() (gas: 364) -SafeCastLibTest:testFailSafeCastTo64() (gas: 321) -SafeCastLibTest:testFailSafeCastTo8() (gas: 296) -SafeCastLibTest:testFailSafeCastTo96() (gas: 321) -SafeCastLibTest:testSafeCastTo128() (gas: 449) -SafeCastLibTest:testSafeCastTo160() (gas: 470) +SafeCastLibTest:testFailSafeCastTo224() (gas: 320) +SafeCastLibTest:testFailSafeCastTo248() (gas: 343) +SafeCastLibTest:testFailSafeCastTo32() (gas: 319) +SafeCastLibTest:testFailSafeCastTo64() (gas: 364) +SafeCastLibTest:testFailSafeCastTo8() (gas: 339) +SafeCastLibTest:testFailSafeCastTo96() (gas: 365) +SafeCastLibTest:testSafeCastTo128() (gas: 471) +SafeCastLibTest:testSafeCastTo160() (gas: 469) SafeCastLibTest:testSafeCastTo192() (gas: 471) -SafeCastLibTest:testSafeCastTo224() (gas: 491) -SafeCastLibTest:testSafeCastTo248() (gas: 427) -SafeCastLibTest:testSafeCastTo32() (gas: 471) -SafeCastLibTest:testSafeCastTo64() (gas: 470) -SafeCastLibTest:testSafeCastTo8() (gas: 469) -SafeCastLibTest:testSafeCastTo96() (gas: 469) -SafeTransferLibTest:testApproveWithMissingReturn() (gas: 30751) -SafeTransferLibTest:testApproveWithNonContract() (gas: 3035) -SafeTransferLibTest:testApproveWithReturnsTooMuch() (gas: 31134) -SafeTransferLibTest:testApproveWithStandardERC20() (gas: 30882) -SafeTransferLibTest:testFailApproveWithReturnsFalse() (gas: 5627) -SafeTransferLibTest:testFailApproveWithReturnsTooLittle() (gas: 5568) -SafeTransferLibTest:testFailApproveWithReverting() (gas: 5502) -SafeTransferLibTest:testFailTransferETHToContractWithoutFallback() (gas: 7244) -SafeTransferLibTest:testFailTransferFromWithReturnsFalse() (gas: 13663) -SafeTransferLibTest:testFailTransferFromWithReturnsTooLittle() (gas: 13544) -SafeTransferLibTest:testFailTransferFromWithReverting() (gas: 9757) -SafeTransferLibTest:testFailTransferWithReturnsFalse() (gas: 8532) -SafeTransferLibTest:testFailTransferWithReturnsTooLittle() (gas: 8538) -SafeTransferLibTest:testFailTransferWithReverting() (gas: 8494) -SafeTransferLibTest:testTransferETH() (gas: 34592) -SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 49188) -SafeTransferLibTest:testTransferFromWithNonContract() (gas: 3035) -SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 49812) -SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 47605) -SafeTransferLibTest:testTransferWithMissingReturn() (gas: 36669) -SafeTransferLibTest:testTransferWithNonContract() (gas: 3012) -SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 37115) -SafeTransferLibTest:testTransferWithStandardERC20() (gas: 36699) -WETHTest:testDeposit() (gas: 63260) -WETHTest:testFallbackDeposit() (gas: 63524) -WETHTest:testPartialWithdraw() (gas: 73281) +SafeCastLibTest:testSafeCastTo224() (gas: 470) +SafeCastLibTest:testSafeCastTo248() (gas: 449) +SafeCastLibTest:testSafeCastTo32() (gas: 493) +SafeCastLibTest:testSafeCastTo64() (gas: 448) +SafeCastLibTest:testSafeCastTo8() (gas: 468) +SafeCastLibTest:testSafeCastTo96() (gas: 448) +SafeTransferLibTest:testApproveWithMissingReturn() (gas: 30759) +SafeTransferLibTest:testApproveWithNonContract() (gas: 3032) +SafeTransferLibTest:testApproveWithReturnsTooMuch() (gas: 31117) +SafeTransferLibTest:testApproveWithStandardERC20() (gas: 30845) +SafeTransferLibTest:testFailApproveWithReturnsFalse() (gas: 5610) +SafeTransferLibTest:testFailApproveWithReturnsTooLittle() (gas: 5553) +SafeTransferLibTest:testFailApproveWithReverting() (gas: 5575) +SafeTransferLibTest:testFailTransferETHToContractWithoutFallback() (gas: 7266) +SafeTransferLibTest:testFailTransferFromWithReturnsFalse() (gas: 13640) +SafeTransferLibTest:testFailTransferFromWithReturnsTooLittle() (gas: 13545) +SafeTransferLibTest:testFailTransferFromWithReverting() (gas: 9779) +SafeTransferLibTest:testFailTransferWithReturnsFalse() (gas: 8560) +SafeTransferLibTest:testFailTransferWithReturnsTooLittle() (gas: 8479) +SafeTransferLibTest:testFailTransferWithReverting() (gas: 8500) +SafeTransferLibTest:testTransferETH() (gas: 34636) +SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 49200) +SafeTransferLibTest:testTransferFromWithNonContract() (gas: 3002) +SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 49825) +SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 47618) +SafeTransferLibTest:testTransferWithMissingReturn() (gas: 36671) +SafeTransferLibTest:testTransferWithNonContract() (gas: 3053) +SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 37074) +SafeTransferLibTest:testTransferWithStandardERC20() (gas: 36745) +WETHTest:testDeposit() (gas: 63238) +WETHTest:testFallbackDeposit() (gas: 63546) +WETHTest:testPartialWithdraw() (gas: 73259) WETHTest:testWithdraw() (gas: 54360) diff --git a/src/utils/SafeTransferLib.sol b/src/utils/SafeTransferLib.sol index e4d911f8..90d3437d 100644 --- a/src/utils/SafeTransferLib.sol +++ b/src/utils/SafeTransferLib.sol @@ -5,11 +5,8 @@ import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol) -/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. -/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. +/// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller. library SafeTransferLib { - event Debug(bool one, bool two, uint256 retsize); - /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ @@ -38,25 +35,27 @@ library SafeTransferLib { bool success; assembly { - // Get a pointer to some free memory. - let freeMemoryPointer := mload(0x40) + // We'll write our calldata to this slot below, but restore it later. + let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. - mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) - mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. - mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. - mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. + mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000) + mstore(4, from) // Append the "from" argument. + mstore(36, to) // Append the "to" argument. + mstore(68, amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), - // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. - // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. - // Counterintuitively, this call must be positioned second to the or() call in the - // surrounding and() call or else returndatasize() will be zero during the computation. - call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) + // We use 100 because that's the total length of our calldata (4 + 32 * 3) + // Counterintuitively, this call() must be positioned after the or() in the + // surrounding and() because and() evaluates its arguments from right to left. + call(gas(), token, 0, 0, 100, 0, 32) ) + + mstore(0x60, 0) // Restore the zero slot to zero. + mstore(0x40, memPointer) // Restore the memPointer. } require(success, "TRANSFER_FROM_FAILED"); @@ -70,24 +69,26 @@ library SafeTransferLib { bool success; assembly { - // Get a pointer to some free memory. - let freeMemoryPointer := mload(0x40) + // We'll write our calldata to this slot below, but restore it later. + let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. - mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) - mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. - mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. + mstore(0, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) + mstore(4, to) // Append the "to" argument. + mstore(36, amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), - // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. - // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. - // Counterintuitively, this call must be positioned second to the or() call in the - // surrounding and() call or else returndatasize() will be zero during the computation. - call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) + // We use 68 because that's the total length of our calldata (4 + 32 * 2) + // Counterintuitively, this call() must be positioned after the or() in the + // surrounding and() because and() evaluates its arguments from right to left. + call(gas(), token, 0, 0, 68, 0, 32) ) + + mstore(0x60, 0) // Restore the zero slot to zero. + mstore(0x40, memPointer) // Restore the memPointer. } require(success, "TRANSFER_FAILED"); @@ -101,24 +102,26 @@ library SafeTransferLib { bool success; assembly { - // Get a pointer to some free memory. - let freeMemoryPointer := mload(0x40) + // We'll write our calldata to this slot below, but restore it later. + let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. - mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) - mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. - mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. + mstore(0, 0x095ea7b300000000000000000000000000000000000000000000000000000000) + mstore(4, to) // Append the "to" argument. + mstore(36, amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), - // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. - // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. - // Counterintuitively, this call must be positioned second to the or() call in the - // surrounding and() call or else returndatasize() will be zero during the computation. - call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) + // We use 68 because that's the total length of our calldata (4 + 32 * 2) + // Counterintuitively, this call() must be positioned after the or() in the + // surrounding and() because and() evaluates its arguments from right to left. + call(gas(), token, 0, 0, 68, 0, 32) ) + + mstore(0x60, 0) // Restore the zero slot to zero. + mstore(0x40, memPointer) // Restore the memPointer. } require(success, "APPROVE_FAILED"); From 81924cd5b3c2781a70734ae989c44b179344b198 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 12 May 2022 23:36:35 -0700 Subject: [PATCH 10/44] =?UTF-8?q?=E2=9C=A8=20Logarithm,=20naturally=20(#19?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: t11s --- .gas-snapshot | 70 ++++++++++++++++-------------- src/test/BitwiseLib.t.sol | 17 ++++++++ src/test/FixedPointMathLib.t.sol | 48 +++++++++++++++++++++ src/utils/BitwiseLib.sol | 24 +++++++++++ src/utils/FixedPointMathLib.sol | 73 ++++++++++++++++++++++++++++++++ 5 files changed, 200 insertions(+), 32 deletions(-) create mode 100644 src/test/BitwiseLib.t.sol create mode 100644 src/utils/BitwiseLib.sol diff --git a/.gas-snapshot b/.gas-snapshot index b0313e5a..e9fbd206 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -13,6 +13,7 @@ AuthTest:testSetAuthorityAsOwnerWithOutOfOrderAuthority() (gas: 226463) AuthTest:testSetAuthorityWithPermissiveAuthority() (gas: 125918) AuthTest:testSetOwnerAsOwner() (gas: 15276) AuthTest:testSetOwnerWithPermissiveAuthority() (gas: 127906) +BitwiseLibTest:testIlog() (gas: 283929) Bytes32AddressLibTest:testFillLast12Bytes() (gas: 223) Bytes32AddressLibTest:testFromLast20Bytes() (gas: 191) CREATE3Test:testDeployERC20() (gas: 852410) @@ -119,11 +120,11 @@ ERC4626Test:testFailRedeemWithNoShareAmount() (gas: 32333) ERC4626Test:testFailRedeemWithNotEnoughShareAmount() (gas: 203599) ERC4626Test:testFailRedeemZero() (gas: 7955) ERC4626Test:testFailWithdrawWithNoUnderlyingAmount() (gas: 32286) -ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203539) -ERC4626Test:testMintZero() (gas: 54520) -ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411122) -ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286084) -ERC4626Test:testWithdrawZero() (gas: 52352) +ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203545) +ERC4626Test:testMintZero() (gas: 54526) +ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411132) +ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286088) +ERC4626Test:testWithdrawZero() (gas: 52349) ERC721Test:testApprove() (gas: 78427) ERC721Test:testApproveAll() (gas: 31086) ERC721Test:testApproveBurn() (gas: 65584) @@ -163,19 +164,24 @@ ERC721Test:testTransferFrom() (gas: 86347) ERC721Test:testTransferFromApproveAll() (gas: 92897) ERC721Test:testTransferFromSelf() (gas: 64820) FixedPointMathLibTest:testDivWadDown() (gas: 831) -FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 412) -FixedPointMathLibTest:testDivWadUp() (gas: 927) -FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 494) -FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 308) -FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 353) +FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 435) +FixedPointMathLibTest:testDivWadUp() (gas: 971) +FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 450) +FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 330) +FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 331) FixedPointMathLibTest:testFailMulDivDownZeroDenominator() (gas: 316) -FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 339) +FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 296) +FixedPointMathLibTest:testLnWad() (gas: 2278) +FixedPointMathLibTest:testLnWadBig() (gas: 2298) +FixedPointMathLibTest:testLnWadNegative() (gas: 232) +FixedPointMathLibTest:testLnWadOverfloww() (gas: 232) +FixedPointMathLibTest:testLnWadSmall() (gas: 2936) FixedPointMathLibTest:testMulDivDown() (gas: 1905) FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 729) FixedPointMathLibTest:testMulDivUp() (gas: 2272) -FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 824) -FixedPointMathLibTest:testMulWadDown() (gas: 821) -FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 865) +FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 846) +FixedPointMathLibTest:testMulWadDown() (gas: 844) +FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 843) FixedPointMathLibTest:testMulWadUp() (gas: 980) FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 958) FixedPointMathLibTest:testRPow() (gas: 2142) @@ -231,29 +237,29 @@ SafeCastLibTest:testSafeCastTo32() (gas: 493) SafeCastLibTest:testSafeCastTo64() (gas: 448) SafeCastLibTest:testSafeCastTo8() (gas: 468) SafeCastLibTest:testSafeCastTo96() (gas: 448) -SafeTransferLibTest:testApproveWithMissingReturn() (gas: 30759) -SafeTransferLibTest:testApproveWithNonContract() (gas: 3032) -SafeTransferLibTest:testApproveWithReturnsTooMuch() (gas: 31117) -SafeTransferLibTest:testApproveWithStandardERC20() (gas: 30845) -SafeTransferLibTest:testFailApproveWithReturnsFalse() (gas: 5610) -SafeTransferLibTest:testFailApproveWithReturnsTooLittle() (gas: 5553) -SafeTransferLibTest:testFailApproveWithReverting() (gas: 5575) +SafeTransferLibTest:testApproveWithMissingReturn() (gas: 30753) +SafeTransferLibTest:testApproveWithNonContract() (gas: 3035) +SafeTransferLibTest:testApproveWithReturnsTooMuch() (gas: 31111) +SafeTransferLibTest:testApproveWithStandardERC20() (gas: 30839) +SafeTransferLibTest:testFailApproveWithReturnsFalse() (gas: 5604) +SafeTransferLibTest:testFailApproveWithReturnsTooLittle() (gas: 5547) +SafeTransferLibTest:testFailApproveWithReverting() (gas: 5569) SafeTransferLibTest:testFailTransferETHToContractWithoutFallback() (gas: 7266) SafeTransferLibTest:testFailTransferFromWithReturnsFalse() (gas: 13640) SafeTransferLibTest:testFailTransferFromWithReturnsTooLittle() (gas: 13545) SafeTransferLibTest:testFailTransferFromWithReverting() (gas: 9779) -SafeTransferLibTest:testFailTransferWithReturnsFalse() (gas: 8560) -SafeTransferLibTest:testFailTransferWithReturnsTooLittle() (gas: 8479) -SafeTransferLibTest:testFailTransferWithReverting() (gas: 8500) +SafeTransferLibTest:testFailTransferWithReturnsFalse() (gas: 8554) +SafeTransferLibTest:testFailTransferWithReturnsTooLittle() (gas: 8473) +SafeTransferLibTest:testFailTransferWithReverting() (gas: 8494) SafeTransferLibTest:testTransferETH() (gas: 34636) -SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 49200) -SafeTransferLibTest:testTransferFromWithNonContract() (gas: 3002) -SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 49825) -SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 47618) -SafeTransferLibTest:testTransferWithMissingReturn() (gas: 36671) -SafeTransferLibTest:testTransferWithNonContract() (gas: 3053) -SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 37074) -SafeTransferLibTest:testTransferWithStandardERC20() (gas: 36745) +SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 49205) +SafeTransferLibTest:testTransferFromWithNonContract() (gas: 3014) +SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 49830) +SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 47623) +SafeTransferLibTest:testTransferWithMissingReturn() (gas: 36668) +SafeTransferLibTest:testTransferWithNonContract() (gas: 3056) +SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 37071) +SafeTransferLibTest:testTransferWithStandardERC20() (gas: 36742) WETHTest:testDeposit() (gas: 63238) WETHTest:testFallbackDeposit() (gas: 63546) WETHTest:testPartialWithdraw() (gas: 73259) diff --git a/src/test/BitwiseLib.t.sol b/src/test/BitwiseLib.t.sol new file mode 100644 index 00000000..c759ef5e --- /dev/null +++ b/src/test/BitwiseLib.t.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity 0.8.10; + +import {DSTestPlus} from "./utils/DSTestPlus.sol"; + +import {BitwiseLib} from "../utils/BitwiseLib.sol"; + +contract BitwiseLibTest is DSTestPlus { + function testIlog() public { + assertEq(BitwiseLib.ilog2(0), 0); + for (uint256 i = 1; i < 255; i++) { + assertEq(BitwiseLib.ilog2((1 << i) - 1), i - 1); + assertEq(BitwiseLib.ilog2((1 << i)), i); + assertEq(BitwiseLib.ilog2((1 << i) + 1), i); + } + } +} diff --git a/src/test/FixedPointMathLib.t.sol b/src/test/FixedPointMathLib.t.sol index 8dece878..6a2c1cde 100644 --- a/src/test/FixedPointMathLib.t.sol +++ b/src/test/FixedPointMathLib.t.sol @@ -108,6 +108,54 @@ contract FixedPointMathLibTest is DSTestPlus { FixedPointMathLib.mulDivUp(1e18, 1e18, 0); } + function testLnWad() public { + assertEq(FixedPointMathLib.lnWad(1e18), 0); + + // Actual: 999999999999999999.8674576… + assertEq(FixedPointMathLib.lnWad(2718281828459045235), 999999999999999999); + + // Actual: 2461607324344817917.963296… + assertEq(FixedPointMathLib.lnWad(11723640096265400935), 2461607324344817918); + } + + function testLnWadSmall() public { + // Actual: -41446531673892822312.3238461… + assertEq(FixedPointMathLib.lnWad(1), -41446531673892822313); + + // Actual: -37708862055609454006.40601608… + assertEq(FixedPointMathLib.lnWad(42), -37708862055609454007); + + // Actual: -32236191301916639576.251880365581… + assertEq(FixedPointMathLib.lnWad(1e4), -32236191301916639577); + + // Actual: -20723265836946411156.161923092… + assertEq(FixedPointMathLib.lnWad(1e9), -20723265836946411157); + } + + function testLnWadBig() public { + // Actual: 135305999368893231589.070344787… + assertEq(FixedPointMathLib.lnWad(2**255 - 1), 135305999368893231589); + + // Actual: 76388489021297880288.605614463571… + assertEq(FixedPointMathLib.lnWad(2**170), 76388489021297880288); + + // Actual: 47276307437780177293.081865… + assertEq(FixedPointMathLib.lnWad(2**128), 47276307437780177293); + } + + function testLnWadNegative() public { + // TODO: Blocked on + // hevm.expectRevert(FixedPointMathLib.LnNegativeUndefined.selector); + // FixedPointMathLib.lnWad(-1); + // FixedPointMathLib.lnWad(-2**255); + } + + function testLnWadOverfloww() public { + // TODO: Blocked on + // hevm.expectRevert(FixedPointMathLib.Overflow.selector); + // FixedPointMathLib.lnWad(0); + } + function testRPow() public { assertEq(FixedPointMathLib.rpow(2e27, 2, 1e27), 4e27); assertEq(FixedPointMathLib.rpow(2e18, 2, 1e18), 4e18); diff --git a/src/utils/BitwiseLib.sol b/src/utils/BitwiseLib.sol new file mode 100644 index 00000000..7feb3e4c --- /dev/null +++ b/src/utils/BitwiseLib.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +/// @notice Bitwise library with operations for bit strings and integers. +library BitwiseLib { + // Integer log2 + // Closely related to count-leading-zeros. + // See + // @returns floor(log2(x)) if x is nonzero, otherwise 0. + // This is the same as the location of the highest set bit. + // Consumes 232 gas. This could have been an 3 gas EVM opcode though. + function ilog2(uint256 x) internal returns (uint256 r) { + assembly { + r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) + r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) + r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) + r := or(r, shl(4, lt(0xffff, shr(r, x)))) + r := or(r, shl(3, lt(0xff, shr(r, x)))) + r := or(r, shl(2, lt(0xf, shr(r, x)))) + r := or(r, shl(1, lt(0x3, shr(r, x)))) + r := or(r, lt(0x1, shr(r, x))) + } + } +} diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index 2bee178a..c38095fa 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -1,10 +1,16 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; +import {BitwiseLib} from "./BitwiseLib.sol"; + /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { + error Overflow(); + + error LnNegativeUndefined(); + /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ @@ -27,6 +33,73 @@ library FixedPointMathLib { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } + // Computes ln(x) in 1e18 fixed point. + // Reverts if x is negative or zero. + // @param x The number to compute ln(x) for. + // @returns Approximately ln(x / 1e18) * 1e18 if x is strictly positive, + // reverts with `LnNegativeUndefined()` if x is negative, and with + // `Overflow()` if x is zero. + // Consumes about 670 gas. + function lnWad(int256 x) internal returns (int256 r) { + unchecked { + if (x < 1) { + if (x < 0) revert LnNegativeUndefined(); + revert Overflow(); + } + + // We want to convert x from 10**18 fixed point to 2**96 fixed point. + // We do this by multiplying by 2**96 / 10**18. + // But since ln(x * C) = ln(x) + ln(C), we can simply do nothing here + // and add ln(2**96 / 10**18) at the end. + + // Reduce range of x to (1, 2) * 2**96 + // ln(2^k * x) = k * ln(2) + ln(x) + int256 k = int256(BitwiseLib.ilog2(uint256(x))) - 96; + x <<= uint256(159 - k); + x = int256(uint256(x) >> 159); + + // Evaluate using a (8, 8)-term rational approximation + // p is made monic, we will multiply by a scale factor later + int256 p = x + 3273285459638523848632254066296; + p = ((p * x) >> 96) + 24828157081833163892658089445524; + p = ((p * x) >> 96) + 43456485725739037958740375743393; + p = ((p * x) >> 96) - 11111509109440967052023855526967; + p = ((p * x) >> 96) - 45023709667254063763336534515857; + p = ((p * x) >> 96) - 14706773417378608786704636184526; + p = p * x - (795164235651350426258249787498 << 96); + // We leave p in 2**192 basis so we don't need to scale it back up for the division. + // q is monic by convention + int256 q = x + 5573035233440673466300451813936; + q = ((q * x) >> 96) + 71694874799317883764090561454958; + q = ((q * x) >> 96) + 283447036172924575727196451306956; + q = ((q * x) >> 96) + 401686690394027663651624208769553; + q = ((q * x) >> 96) + 204048457590392012362485061816622; + q = ((q * x) >> 96) + 31853899698501571402653359427138; + q = ((q * x) >> 96) + 909429971244387300277376558375; + assembly { + // Div in assembly because solidity adds a zero check despite the `unchecked`. + // The q polynomial is known not to have zeros in the domain. (All roots are complex) + // No scaling required because p is already 2**96 too large. + r := sdiv(p, q) + } + // r is in the range (0, 0.125) * 2**96 + + // Finalization, we need to + // * multiply by the scale factor s = 5.549… + // * add ln(2**96 / 10**18) + // * add k * ln(2) + // * multiply by 10**18 / 2**96 = 5**18 >> 78 + // mul s * 5e18 * 2**96, base is now 5**18 * 2**192 + r *= 1677202110996718588342820967067443963516166; + // add ln(2) * k * 5e18 * 2**192 + r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k; + // add ln(2**96 / 10**18) * 5e18 * 2**192 + r += 600920179829731861736702779321621459595472258049074101567377883020018308; + // base conversion: mul 2**18 / 2**192 + r >>= 174; + } + } + /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ From 7e5280d8e8c31ed948b46e4e3db6bf830cc6f87c Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 12 May 2022 23:42:10 -0700 Subject: [PATCH 11/44] =?UTF-8?q?=E2=9C=A8=20FixedMathLib:=20expWadDown()?= =?UTF-8?q?=20(#171)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: t11s --- src/test/FixedPointMathLib.t.sol | 48 +++++++++++++++++++++++++ src/test/utils/DSTestPlus.sol | 17 +++++++++ src/utils/FixedPointMathLib.sol | 60 +++++++++++++++++++++++++++++++- 3 files changed, 124 insertions(+), 1 deletion(-) diff --git a/src/test/FixedPointMathLib.t.sol b/src/test/FixedPointMathLib.t.sol index 6a2c1cde..e7119805 100644 --- a/src/test/FixedPointMathLib.t.sol +++ b/src/test/FixedPointMathLib.t.sol @@ -6,6 +6,54 @@ import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol"; contract FixedPointMathLibTest is DSTestPlus { + function testExpWad() public { + assertEq(FixedPointMathLib.expWad(-42139678854452767551), 0); + + assertEq(FixedPointMathLib.expWad(-3e18), 49787068367863942); + assertEq(FixedPointMathLib.expWad(-2e18), 135335283236612691); + assertEq(FixedPointMathLib.expWad(-1e18), 367879441171442321); + + assertEq(FixedPointMathLib.expWad(-0.5e18), 606530659712633423); + assertEq(FixedPointMathLib.expWad(-0.3e18), 740818220681717866); + + assertEq( + FixedPointMathLib.expWad(0), + 999999999999999999 + // True value: 1000000000000000000 (off by 1 wei) + ); + + assertEq(FixedPointMathLib.expWad(0.3e18), 1349858807576003103); + assertEq(FixedPointMathLib.expWad(0.5e18), 1648721270700128146); + + assertEq(FixedPointMathLib.expWad(1e18), 2718281828459045235); + assertEq(FixedPointMathLib.expWad(2e18), 7389056098930650227); + assertEq(FixedPointMathLib.expWad(3e18), 20085536923187667740); + + assertEq( + FixedPointMathLib.expWad(10e18), + 22026465794806716516_861 + // True value: 22026465794806716516_957 (21 digits of precision) + ); + + assertEq( + FixedPointMathLib.expWad(50e18), + 5184705528587072464_117909654408922782335 + // True value: 5184705528587072464_087453322933485384827 (19 digits of precision) + ); + + assertEq( + FixedPointMathLib.expWad(100e18), + 2688117141816135448_3982463551405023462056137701762092799015183 + // True value: 2688117141816135448_4126255515800135873611118773741922415191608 (20 digits of precision) + ); + + assertEq( + FixedPointMathLib.expWad(135305999368893231588), + 578960446186580976498_09650847705537384645150747719143657509713249170749644355 + // True value: 578960446186580976498_16762928942336782129491980154662247847962410455084893091 (21 digits of precision) + ); + } + function testMulWadDown() public { assertEq(FixedPointMathLib.mulWadDown(2.5e18, 0.5e18), 1.25e18); assertEq(FixedPointMathLib.mulWadDown(3e18, 1e18), 3e18); diff --git a/src/test/utils/DSTestPlus.sol b/src/test/utils/DSTestPlus.sol index afd03f73..93c18c12 100644 --- a/src/test/utils/DSTestPlus.sol +++ b/src/test/utils/DSTestPlus.sol @@ -108,6 +108,23 @@ contract DSTestPlus is DSTest { } } + function assertApproxEq( + int256 a, + int256 b, + uint256 maxDelta + ) internal virtual { + int256 delta = a > b ? a - b : b - a; + + if (delta > int256(maxDelta)) { + emit log("Error: a ~= b not satisfied [uint]"); + emit log_named_int(" Expected", b); + emit log_named_int(" Actual", a); + emit log_named_uint(" Max Delta", maxDelta); + emit log_named_int(" Delta", delta); + fail(); + } + } + function assertRelApproxEq( uint256 a, uint256 b, diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index c38095fa..596c62f1 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -5,7 +5,7 @@ import {BitwiseLib} from "./BitwiseLib.sol"; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) -/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) +/// @author Inspired by Balancer (https://github.com/balancer-labs/balancer-v2-monorepo/tree/master/pkg/solidity-utils/contracts/math) library FixedPointMathLib { error Overflow(); @@ -33,6 +33,64 @@ library FixedPointMathLib { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } + function expWad(int256 x) internal pure returns (int256 r) { + unchecked { + // When the result is < 0.5 we return zero. This happens when + // x <= floor(log(0.5e18) * 1e18) ~ -42e18 + if (x <= -42139678854452767551) return 0; + + // When the result is > (2**255 - 1) / 1e18 we can not represent it + // as an int256. This happens when x >= floor(log((2**255 -1) / 1e18) * 1e18) ~ 135. + if (x >= 135305999368893231589) revert("EXP_OVERFLOW"); + + // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 + // for more intermediate precision and a binary basis. This base conversion + // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. + x = (x << 78) / 5**18; + + // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers of two + // such that exp(x) = exp(x') * 2**k, where k is an integer. + // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). + int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96; + x = x - k * 54916777467707473351141471128; + + // k is in the range [-61, 195]. + + // Evaluate using a (6, 7)-term rational approximation. + // p is made monic, we'll multiply by a scale factor later. + int256 y = x + 1346386616545796478920950773328; + y = ((y * x) >> 96) + 57155421227552351082224309758442; + int256 p = y + x - 94201549194550492254356042504812; + p = ((p * y) >> 96) + 28719021644029726153956944680412240; + p = p * x + (4385272521454847904632057985693276 << 96); + + // We leave p in 2**192 basis so we don't need to scale it back up for the division. + int256 q = x - 2855989394907223263936484059900; + q = ((q * x) >> 96) + 50020603652535783019961831881945; + q = ((q * x) >> 96) - 533845033583426703283633433725380; + q = ((q * x) >> 96) + 3604857256930695427073651918091429; + q = ((q * x) >> 96) - 14423608567350463180887372962807573; + q = ((q * x) >> 96) + 26449188498355588339934803723976023; + + assembly { + // Div in assembly because solidity adds a zero check despite the `unchecked`. + // The q polynomial won't have zeros in the domain as all its roots are complex. + // No scaling is necessary because p is already 2**96 too large. + r := sdiv(p, q) + } + + // r should be in the range (0.09, 0.25) * 2**96. + + // We now need to multiply r by: + // - the scale factor s = ~6.031367120. + // - the 2**k factor from the range reduction. + // - the 1e18 / 2**96 factor for base conversion. + // We do this all at once, with an intermediate result in 2**213 + // basis, so the final right shift is always by a positive amount. + r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)); + } + } + // Computes ln(x) in 1e18 fixed point. // Reverts if x is negative or zero. // @param x The number to compute ln(x) for. From f918d2690910cdcc0f22e104d8c729243b2a70de Mon Sep 17 00:00:00 2001 From: t11s Date: Fri, 13 May 2022 00:04:09 -0700 Subject: [PATCH 12/44] =?UTF-8?q?=F0=9F=93=9D=20Cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 324 ++++++++++++++++---------------- src/utils/FixedPointMathLib.sol | 41 ++-- 2 files changed, 185 insertions(+), 180 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 1a91e953..6b017a7a 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,18 +1,18 @@ -AuthTest:testCallFunctionAsOwner() (gas: 29871) -AuthTest:testCallFunctionWithPermissiveAuthority() (gas: 124249) +AuthTest:testCallFunctionAsOwner() (gas: 29828) +AuthTest:testCallFunctionWithPermissiveAuthority() (gas: 124270) AuthTest:testFailCallFunctionAsNonOwner() (gas: 15491) -AuthTest:testFailCallFunctionAsOwnerWithOutOfOrderAuthority() (gas: 136021) -AuthTest:testFailCallFunctionWithRestrictiveAuthority() (gas: 129201) -AuthTest:testFailSetAuthorityAsNonOwner() (gas: 18260) +AuthTest:testFailCallFunctionAsOwnerWithOutOfOrderAuthority() (gas: 136042) +AuthTest:testFailCallFunctionWithRestrictiveAuthority() (gas: 129178) +AuthTest:testFailSetAuthorityAsNonOwner() (gas: 18304) AuthTest:testFailSetAuthorityWithRestrictiveAuthority() (gas: 129078) -AuthTest:testFailSetOwnerAsNonOwner() (gas: 15609) -AuthTest:testFailSetOwnerAsOwnerWithOutOfOrderAuthority() (gas: 136161) -AuthTest:testFailSetOwnerWithRestrictiveAuthority() (gas: 129242) -AuthTest:testSetAuthorityAsOwner() (gas: 32302) -AuthTest:testSetAuthorityAsOwnerWithOutOfOrderAuthority() (gas: 226396) -AuthTest:testSetAuthorityWithPermissiveAuthority() (gas: 125963) -AuthTest:testSetOwnerAsOwner() (gas: 15298) -AuthTest:testSetOwnerWithPermissiveAuthority() (gas: 127884) +AuthTest:testFailSetOwnerAsNonOwner() (gas: 15587) +AuthTest:testFailSetOwnerAsOwnerWithOutOfOrderAuthority() (gas: 136118) +AuthTest:testFailSetOwnerWithRestrictiveAuthority() (gas: 129264) +AuthTest:testSetAuthorityAsOwner() (gas: 32235) +AuthTest:testSetAuthorityAsOwnerWithOutOfOrderAuthority() (gas: 226463) +AuthTest:testSetAuthorityWithPermissiveAuthority() (gas: 125918) +AuthTest:testSetOwnerAsOwner() (gas: 15276) +AuthTest:testSetOwnerWithPermissiveAuthority() (gas: 127906) Bytes32AddressLibTest:testFillLast12Bytes() (gas: 223) Bytes32AddressLibTest:testFromLast20Bytes() (gas: 191) CREATE3Test:testDeployERC20() (gas: 852410) @@ -20,46 +20,46 @@ CREATE3Test:testFailDoubleDeployDifferentBytecode() (gas: 9079256848778914164) CREATE3Test:testFailDoubleDeploySameBytecode() (gas: 9079256848778906218) DSTestPlusTest:testBound() (gas: 14208) DSTestPlusTest:testBrutalizeMemory() (gas: 823) -DSTestPlusTest:testFailBoundMinBiggerThanMax() (gas: 309) -DSTestPlusTest:testMeasuringGas() (gas: 24622) -DSTestPlusTest:testRelApproxEqBothZeroesPasses() (gas: 413) -ERC1155Test:testApproveAll() (gas: 31009) -ERC1155Test:testBatchBalanceOf() (gas: 157631) -ERC1155Test:testBatchBurn() (gas: 151074) -ERC1155Test:testBatchMintToEOA() (gas: 137337) -ERC1155Test:testBatchMintToERC1155Recipient() (gas: 942650) -ERC1155Test:testBurn() (gas: 38598) +DSTestPlusTest:testFailBoundMinBiggerThanMax() (gas: 287) +DSTestPlusTest:testMeasuringGas() (gas: 24600) +DSTestPlusTest:testRelApproxEqBothZeroesPasses() (gas: 391) +ERC1155Test:testApproveAll() (gas: 31053) +ERC1155Test:testBatchBalanceOf() (gas: 157587) +ERC1155Test:testBatchBurn() (gas: 151051) +ERC1155Test:testBatchMintToEOA() (gas: 137293) +ERC1155Test:testBatchMintToERC1155Recipient() (gas: 942660) +ERC1155Test:testBurn() (gas: 38576) ERC1155Test:testFailBalanceOfBatchWithArrayMismatch() (gas: 7933) -ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136156) -ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 135542) -ERC1155Test:testFailBatchMintToNonERC1155Recipient() (gas: 167292) -ERC1155Test:testFailBatchMintToRevertingERC1155Recipient() (gas: 358811) -ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 310743) -ERC1155Test:testFailBatchMintToZero() (gas: 131737) -ERC1155Test:testFailBatchMintWithArrayMismatch() (gas: 9600) -ERC1155Test:testFailBurnInsufficientBalance() (gas: 34852) -ERC1155Test:testFailMintToNonERC155Recipient() (gas: 68191) -ERC1155Test:testFailMintToRevertingERC155Recipient() (gas: 259435) -ERC1155Test:testFailMintToWrongReturnDataERC155Recipient() (gas: 259389) +ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136177) +ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 135543) +ERC1155Test:testFailBatchMintToNonERC1155Recipient() (gas: 167311) +ERC1155Test:testFailBatchMintToRevertingERC1155Recipient() (gas: 358854) +ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 310745) +ERC1155Test:testFailBatchMintToZero() (gas: 131716) +ERC1155Test:testFailBatchMintWithArrayMismatch() (gas: 9621) +ERC1155Test:testFailBurnInsufficientBalance() (gas: 34830) +ERC1155Test:testFailMintToNonERC155Recipient() (gas: 68192) +ERC1155Test:testFailMintToRevertingERC155Recipient() (gas: 259413) +ERC1155Test:testFailMintToWrongReturnDataERC155Recipient() (gas: 259412) ERC1155Test:testFailMintToZero() (gas: 33705) -ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 321377) -ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 512956) -ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 464847) -ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 286556) -ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 162674) -ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 163555) -ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 63245) -ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance() (gas: 34297) +ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 321355) +ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 512934) +ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 464869) +ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 286535) +ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 162653) +ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 163533) +ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 63267) +ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance() (gas: 34320) ERC1155Test:testFailSafeTransferFromToNonERC155Recipient() (gas: 96510) -ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 287731) -ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 239587) +ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 287732) +ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 239610) ERC1155Test:testFailSafeTransferFromToZero() (gas: 62014) -ERC1155Test:testMintToEOA() (gas: 34765) -ERC1155Test:testMintToERC1155Recipient() (gas: 608328) +ERC1155Test:testMintToEOA() (gas: 34743) +ERC1155Test:testMintToERC1155Recipient() (gas: 608327) ERC1155Test:testSafeBatchTransferFromToEOA() (gas: 297822) ERC1155Test:testSafeBatchTransferFromToERC1155Recipient() (gas: 1122274) -ERC1155Test:testSafeTransferFromSelf() (gas: 64177) -ERC1155Test:testSafeTransferFromToEOA() (gas: 93167) +ERC1155Test:testSafeTransferFromSelf() (gas: 64155) +ERC1155Test:testSafeTransferFromToEOA() (gas: 93168) ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 686500) ERC1155BTest:testApproveAll() (gas: 30947) ERC1155BTest:testBatchBalanceOf() (gas: 157240) @@ -97,160 +97,164 @@ ERC1155BTest:testSafeBatchTransferFromToERC1155Recipient() (gas: 1522381) ERC1155BTest:testSafeTransferFromSelf() (gas: 41780) ERC1155BTest:testSafeTransferFromToEOA() (gas: 582836) ERC1155BTest:testSafeTransferFromToERC1155Recipient() (gas: 1175937) -ERC20Test:testApprove() (gas: 31058) -ERC20Test:testBurn() (gas: 56970) +ERC20Test:testApprove() (gas: 31080) +ERC20Test:testBurn() (gas: 57014) ERC20Test:testFailPermitBadDeadline() (gas: 36924) ERC20Test:testFailPermitBadNonce() (gas: 36874) ERC20Test:testFailPermitPastDeadline() (gas: 10938) ERC20Test:testFailPermitReplay() (gas: 66285) -ERC20Test:testFailTransferFromInsufficientAllowance() (gas: 80882) -ERC20Test:testFailTransferFromInsufficientBalance() (gas: 81358) -ERC20Test:testFailTransferInsufficientBalance() (gas: 52806) -ERC20Test:testInfiniteApproveTransferFrom() (gas: 89793) -ERC20Test:testMint() (gas: 53746) -ERC20Test:testPermit() (gas: 63193) -ERC20Test:testTransfer() (gas: 60272) -ERC20Test:testTransferFrom() (gas: 83777) +ERC20Test:testFailTransferFromInsufficientAllowance() (gas: 80837) +ERC20Test:testFailTransferFromInsufficientBalance() (gas: 81336) +ERC20Test:testFailTransferInsufficientBalance() (gas: 52784) +ERC20Test:testInfiniteApproveTransferFrom() (gas: 89748) +ERC20Test:testMint() (gas: 53768) +ERC20Test:testPermit() (gas: 63237) +ERC20Test:testTransfer() (gas: 60228) +ERC20Test:testTransferFrom() (gas: 83821) ERC4626Test:testFailDepositWithNoApproval() (gas: 13345) ERC4626Test:testFailDepositWithNotEnoughApproval() (gas: 86963) -ERC4626Test:testFailDepositZero() (gas: 7768) -ERC4626Test:testFailMintWithNoApproval() (gas: 13290) +ERC4626Test:testFailDepositZero() (gas: 7790) +ERC4626Test:testFailMintWithNoApproval() (gas: 13246) ERC4626Test:testFailRedeemWithNoShareAmount() (gas: 32333) ERC4626Test:testFailRedeemWithNotEnoughShareAmount() (gas: 203605) ERC4626Test:testFailRedeemZero() (gas: 7955) ERC4626Test:testFailWithdrawWithNoUnderlyingAmount() (gas: 32286) -ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203588) +ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203545) ERC4626Test:testMintZero() (gas: 54526) -ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411114) +ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411132) ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286088) -ERC4626Test:testWithdrawZero() (gas: 52393) +ERC4626Test:testWithdrawZero() (gas: 52349) ERC721Test:testApprove() (gas: 78427) -ERC721Test:testApproveAll() (gas: 31063) -ERC721Test:testApproveBurn() (gas: 65550) -ERC721Test:testBurn() (gas: 46107) +ERC721Test:testApproveAll() (gas: 31086) +ERC721Test:testApproveBurn() (gas: 65584) +ERC721Test:testBurn() (gas: 46124) ERC721Test:testFailApproveUnAuthorized() (gas: 55598) -ERC721Test:testFailApproveUnMinted() (gas: 10236) -ERC721Test:testFailBalanceOfZeroAddress() (gas: 5555) +ERC721Test:testFailApproveUnMinted() (gas: 10194) +ERC721Test:testFailBalanceOfZeroAddress() (gas: 5576) ERC721Test:testFailBurnUnMinted() (gas: 7857) -ERC721Test:testFailDoubleBurn() (gas: 58943) +ERC721Test:testFailDoubleBurn() (gas: 58986) ERC721Test:testFailDoubleMint() (gas: 53286) -ERC721Test:testFailMintToZero() (gas: 5753) -ERC721Test:testFailOwnerOfUnminted() (gas: 7609) -ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnData() (gas: 159070) +ERC721Test:testFailMintToZero() (gas: 5754) +ERC721Test:testFailOwnerOfUnminted() (gas: 7631) +ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnData() (gas: 159028) ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnDataWithData() (gas: 159825) -ERC721Test:testFailSafeMintToNonERC721Recipient() (gas: 89205) +ERC721Test:testFailSafeMintToNonERC721Recipient() (gas: 89204) ERC721Test:testFailSafeMintToNonERC721RecipientWithData() (gas: 89990) ERC721Test:testFailSafeMintToRevertingERC721Recipient() (gas: 204738) -ERC721Test:testFailSafeMintToRevertingERC721RecipientWithData() (gas: 205512) -ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnData() (gas: 187270) +ERC721Test:testFailSafeMintToRevertingERC721RecipientWithData() (gas: 205556) +ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnData() (gas: 187272) ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData() (gas: 187722) -ERC721Test:testFailSafeTransferFromToNonERC721Recipient() (gas: 117408) -ERC721Test:testFailSafeTransferFromToNonERC721RecipientWithData() (gas: 117867) -ERC721Test:testFailSafeTransferFromToRevertingERC721Recipient() (gas: 233004) +ERC721Test:testFailSafeTransferFromToNonERC721Recipient() (gas: 117409) +ERC721Test:testFailSafeTransferFromToNonERC721RecipientWithData() (gas: 117889) +ERC721Test:testFailSafeTransferFromToRevertingERC721Recipient() (gas: 232982) ERC721Test:testFailSafeTransferFromToRevertingERC721RecipientWithData() (gas: 233391) -ERC721Test:testFailTransferFromNotOwner() (gas: 57872) -ERC721Test:testFailTransferFromToZero() (gas: 53381) -ERC721Test:testFailTransferFromUnOwned() (gas: 8000) -ERC721Test:testFailTransferFromWrongFrom() (gas: 53361) -ERC721Test:testMint() (gas: 54336) -ERC721Test:testSafeMintToEOA() (gas: 56976) -ERC721Test:testSafeMintToERC721Recipient() (gas: 381731) -ERC721Test:testSafeMintToERC721RecipientWithData() (gas: 402875) -ERC721Test:testSafeTransferFromToEOA() (gas: 95649) -ERC721Test:testSafeTransferFromToERC721Recipient() (gas: 440245) -ERC721Test:testSafeTransferFromToERC721RecipientWithData() (gas: 461043) +ERC721Test:testFailTransferFromNotOwner() (gas: 57894) +ERC721Test:testFailTransferFromToZero() (gas: 53359) +ERC721Test:testFailTransferFromUnOwned() (gas: 7999) +ERC721Test:testFailTransferFromWrongFrom() (gas: 53382) +ERC721Test:testMint() (gas: 54360) +ERC721Test:testSafeMintToEOA() (gas: 56974) +ERC721Test:testSafeMintToERC721Recipient() (gas: 381730) +ERC721Test:testSafeMintToERC721RecipientWithData() (gas: 402853) +ERC721Test:testSafeTransferFromToEOA() (gas: 95627) +ERC721Test:testSafeTransferFromToERC721Recipient() (gas: 440223) +ERC721Test:testSafeTransferFromToERC721RecipientWithData() (gas: 461042) ERC721Test:testTransferFrom() (gas: 86347) -ERC721Test:testTransferFromApproveAll() (gas: 92898) -ERC721Test:testTransferFromSelf() (gas: 64776) -FixedPointMathLibTest:testDivWadDown() (gas: 864) -FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 423) -FixedPointMathLibTest:testDivWadUp() (gas: 981) -FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 482) -FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 362) -FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 342) +ERC721Test:testTransferFromApproveAll() (gas: 92897) +ERC721Test:testTransferFromSelf() (gas: 64820) +FixedPointMathLibTest:testDivWadDown() (gas: 831) +FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 412) +FixedPointMathLibTest:testDivWadUp() (gas: 927) +FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 494) +FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 308) +FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 353) FixedPointMathLibTest:testFailMulDivDownZeroDenominator() (gas: 316) -FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 317) -FixedPointMathLibTest:testMulDivDown() (gas: 1861) -FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 751) -FixedPointMathLibTest:testMulDivUp() (gas: 2273) -FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 846) +FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 339) +FixedPointMathLibTest:testMulDivDown() (gas: 1905) +FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 729) +FixedPointMathLibTest:testMulDivUp() (gas: 2272) +FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 824) FixedPointMathLibTest:testMulWadDown() (gas: 821) -FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 886) -FixedPointMathLibTest:testMulWadUp() (gas: 959) -FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 1002) +FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 865) +FixedPointMathLibTest:testMulWadUp() (gas: 980) +FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 958) FixedPointMathLibTest:testRPow() (gas: 2142) FixedPointMathLibTest:testSqrt() (gas: 2156) -MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34292) -MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80556) +MerkleProofTest:testValidProofSupplied() (gas: 991) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 392) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 389) +MerkleProofTest:testVerifyInvalidProofSupplied() (gas: 977) +MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34293) +MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80575) MultiRolesAuthorityTest:testCanCallWithCustomAuthority() (gas: 422681) -MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesPublicCapability() (gas: 247674) -MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesUserWithRole() (gas: 256845) +MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesPublicCapability() (gas: 247696) +MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesUserWithRole() (gas: 256828) MultiRolesAuthorityTest:testSetPublicCapabilities() (gas: 27762) -MultiRolesAuthorityTest:testSetRoleCapabilities() (gas: 28985) -MultiRolesAuthorityTest:testSetRoles() (gas: 29006) +MultiRolesAuthorityTest:testSetRoleCapabilities() (gas: 28968) +MultiRolesAuthorityTest:testSetRoles() (gas: 28971) MultiRolesAuthorityTest:testSetTargetCustomAuthority() (gas: 27976) ReentrancyGuardTest:testFailUnprotectedCall() (gas: 45665) ReentrancyGuardTest:testNoReentrancy() (gas: 7515) ReentrancyGuardTest:testProtectedCall() (gas: 32949) -RolesAuthorityTest:testCanCallPublicCapability() (gas: 33336) -RolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 79601) +RolesAuthorityTest:testCanCallPublicCapability() (gas: 33319) +RolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 79584) RolesAuthorityTest:testSetPublicCapabilities() (gas: 29183) -RolesAuthorityTest:testSetRoleCapabilities() (gas: 30258) -RolesAuthorityTest:testSetRoles() (gas: 28986) -SSTORE2Test:testFailReadInvalidPointer() (gas: 2927) -SSTORE2Test:testFailReadInvalidPointerCustomBounds() (gas: 3099) +RolesAuthorityTest:testSetRoleCapabilities() (gas: 30276) +RolesAuthorityTest:testSetRoles() (gas: 28951) +SSTORE2Test:testFailReadInvalidPointer() (gas: 2905) +SSTORE2Test:testFailReadInvalidPointerCustomBounds() (gas: 3098) SSTORE2Test:testFailReadInvalidPointerCustomStartBound() (gas: 3004) -SSTORE2Test:testFailWriteReadEmptyOutOfBounds() (gas: 34470) +SSTORE2Test:testFailWriteReadEmptyOutOfBounds() (gas: 34448) SSTORE2Test:testFailWriteReadOutOfBounds() (gas: 34426) -SSTORE2Test:testFailWriteReadOutOfStartBound() (gas: 34362) +SSTORE2Test:testFailWriteReadOutOfStartBound() (gas: 34317) SSTORE2Test:testWriteRead() (gas: 53497) SSTORE2Test:testWriteReadCustomBounds() (gas: 34869) -SSTORE2Test:testWriteReadCustomStartBound() (gas: 34740) +SSTORE2Test:testWriteReadCustomStartBound() (gas: 34784) SSTORE2Test:testWriteReadEmptyBound() (gas: 34677) -SSTORE2Test:testWriteReadFullBoundedRead() (gas: 53672) +SSTORE2Test:testWriteReadFullBoundedRead() (gas: 53716) SSTORE2Test:testWriteReadFullStartBound() (gas: 34764) -SafeCastLibTest:testFailSafeCastTo128() (gas: 321) -SafeCastLibTest:testFailSafeCastTo160() (gas: 342) +SafeCastLibTest:testFailSafeCastTo128() (gas: 364) +SafeCastLibTest:testFailSafeCastTo160() (gas: 320) SafeCastLibTest:testFailSafeCastTo192() (gas: 344) -SafeCastLibTest:testFailSafeCastTo224() (gas: 343) -SafeCastLibTest:testFailSafeCastTo248() (gas: 365) -SafeCastLibTest:testFailSafeCastTo32() (gas: 364) -SafeCastLibTest:testFailSafeCastTo64() (gas: 321) -SafeCastLibTest:testFailSafeCastTo8() (gas: 296) -SafeCastLibTest:testFailSafeCastTo96() (gas: 321) -SafeCastLibTest:testSafeCastTo128() (gas: 449) -SafeCastLibTest:testSafeCastTo160() (gas: 470) +SafeCastLibTest:testFailSafeCastTo224() (gas: 320) +SafeCastLibTest:testFailSafeCastTo248() (gas: 343) +SafeCastLibTest:testFailSafeCastTo32() (gas: 319) +SafeCastLibTest:testFailSafeCastTo64() (gas: 364) +SafeCastLibTest:testFailSafeCastTo8() (gas: 339) +SafeCastLibTest:testFailSafeCastTo96() (gas: 365) +SafeCastLibTest:testSafeCastTo128() (gas: 471) +SafeCastLibTest:testSafeCastTo160() (gas: 469) SafeCastLibTest:testSafeCastTo192() (gas: 471) -SafeCastLibTest:testSafeCastTo224() (gas: 491) -SafeCastLibTest:testSafeCastTo248() (gas: 427) -SafeCastLibTest:testSafeCastTo32() (gas: 471) -SafeCastLibTest:testSafeCastTo64() (gas: 470) -SafeCastLibTest:testSafeCastTo8() (gas: 469) -SafeCastLibTest:testSafeCastTo96() (gas: 469) -SafeTransferLibTest:testApproveWithMissingReturn() (gas: 30751) +SafeCastLibTest:testSafeCastTo224() (gas: 470) +SafeCastLibTest:testSafeCastTo248() (gas: 449) +SafeCastLibTest:testSafeCastTo32() (gas: 493) +SafeCastLibTest:testSafeCastTo64() (gas: 448) +SafeCastLibTest:testSafeCastTo8() (gas: 468) +SafeCastLibTest:testSafeCastTo96() (gas: 448) +SafeTransferLibTest:testApproveWithMissingReturn() (gas: 30753) SafeTransferLibTest:testApproveWithNonContract() (gas: 3035) -SafeTransferLibTest:testApproveWithReturnsTooMuch() (gas: 31134) -SafeTransferLibTest:testApproveWithStandardERC20() (gas: 30882) -SafeTransferLibTest:testFailApproveWithReturnsFalse() (gas: 5627) -SafeTransferLibTest:testFailApproveWithReturnsTooLittle() (gas: 5568) -SafeTransferLibTest:testFailApproveWithReverting() (gas: 5502) -SafeTransferLibTest:testFailTransferETHToContractWithoutFallback() (gas: 7244) -SafeTransferLibTest:testFailTransferFromWithReturnsFalse() (gas: 13663) -SafeTransferLibTest:testFailTransferFromWithReturnsTooLittle() (gas: 13544) -SafeTransferLibTest:testFailTransferFromWithReverting() (gas: 9757) -SafeTransferLibTest:testFailTransferWithReturnsFalse() (gas: 8532) -SafeTransferLibTest:testFailTransferWithReturnsTooLittle() (gas: 8538) +SafeTransferLibTest:testApproveWithReturnsTooMuch() (gas: 31111) +SafeTransferLibTest:testApproveWithStandardERC20() (gas: 30839) +SafeTransferLibTest:testFailApproveWithReturnsFalse() (gas: 5604) +SafeTransferLibTest:testFailApproveWithReturnsTooLittle() (gas: 5547) +SafeTransferLibTest:testFailApproveWithReverting() (gas: 5569) +SafeTransferLibTest:testFailTransferETHToContractWithoutFallback() (gas: 7266) +SafeTransferLibTest:testFailTransferFromWithReturnsFalse() (gas: 13640) +SafeTransferLibTest:testFailTransferFromWithReturnsTooLittle() (gas: 13545) +SafeTransferLibTest:testFailTransferFromWithReverting() (gas: 9779) +SafeTransferLibTest:testFailTransferWithReturnsFalse() (gas: 8554) +SafeTransferLibTest:testFailTransferWithReturnsTooLittle() (gas: 8473) SafeTransferLibTest:testFailTransferWithReverting() (gas: 8494) -SafeTransferLibTest:testTransferETH() (gas: 34592) -SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 49188) -SafeTransferLibTest:testTransferFromWithNonContract() (gas: 3035) -SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 49812) -SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 47605) -SafeTransferLibTest:testTransferWithMissingReturn() (gas: 36669) -SafeTransferLibTest:testTransferWithNonContract() (gas: 3012) -SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 37115) -SafeTransferLibTest:testTransferWithStandardERC20() (gas: 36699) -WETHTest:testDeposit() (gas: 63260) -WETHTest:testFallbackDeposit() (gas: 63524) -WETHTest:testPartialWithdraw() (gas: 73281) +SafeTransferLibTest:testTransferETH() (gas: 34636) +SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 49205) +SafeTransferLibTest:testTransferFromWithNonContract() (gas: 3014) +SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 49830) +SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 47623) +SafeTransferLibTest:testTransferWithMissingReturn() (gas: 36668) +SafeTransferLibTest:testTransferWithNonContract() (gas: 3056) +SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 37071) +SafeTransferLibTest:testTransferWithStandardERC20() (gas: 36742) +WETHTest:testDeposit() (gas: 63238) +WETHTest:testFallbackDeposit() (gas: 63546) +WETHTest:testPartialWithdraw() (gas: 73259) WETHTest:testWithdraw() (gas: 54360) diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index 2bee178a..63db5285 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -165,18 +165,20 @@ library FixedPointMathLib { function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { - // This segment is to get a reasonable initial estimate for the Babylonian method. - // If the initial estimate is bad, the number of correct bits increases ~linearly - // each iteration instead of ~quadratically. - // The idea is to get z*z*y within a small factor of x. - // More iterations here gets y in a tighter range. Currently, we will have - // y in [256, 256*2^16). We ensure y>= 256 so that the relative difference - // between y and y+1 is small. If x < 256 this is not possible, but those cases - // are easy enough to verify exhaustively. - z := 181 // The 'correct' value is 1, but this saves a multiply later + z := 181 // The "correct" value is 1, but this saves a multiplication later. + let y := x - // Note that we check y>= 2^(k + 8) but shift right by k bits each branch, - // this is to ensure that if x >= 256, then y >= 256. + + // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad + // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. + + // Goal is to get z*z*y within a small factor of x. More iterations will + // get y in a tighter range. Currently, we will have y in [256, 256*2^16). + // We ensure y >= 256 so that the relative difference between y and y+1 is small. + // That's not possible if x < 256 but we can just verify those cases exhaustively. + + // We check y >= 2^(k + 8) but shift right by k bits + // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) @@ -193,21 +195,21 @@ library FixedPointMathLib { y := shr(16, y) z := shl(8, z) } - // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), - // and either y >= 256, or x < 256. + + // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) - // is in the range (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s=1 + // is in the range (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 // and when s = 256 or 1/256. Since y is in [256, 256*2^16), let a = y/65536, so // that a is in [1/256, 256). Then we can estimate sqrt(y) as // sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18 + // There is no overflow risk here since y < 2^136 after the first branch above. - z := shr(18, mul(z, add(y, 65536))) // A multiply is saved from the initial z := 181 + z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. - // Possibly with a quadratic/cubic polynomial above we could get 4-6. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) @@ -216,12 +218,11 @@ library FixedPointMathLib { z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) - // See https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division. // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This check ensures we return floor. - // Since this case is rare, we choose to save gas on the assignment and - // repeat division in the rare case. - // If you don't care whether floor or ceil is returned, you can skip this. + // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division + // Since this case is rare, we save gas on the assignment and repeat division in the rare case. + // If you don't care whether the floor or ceil square root is returned, you can remove this block. if lt(div(x, z), z) { z := div(x, z) } From 92ee33074e6d733f2192180bfcc1092591313a0b Mon Sep 17 00:00:00 2001 From: t11s Date: Fri, 13 May 2022 00:18:32 -0700 Subject: [PATCH 13/44] =?UTF-8?q?=F0=9F=93=9D=20More=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/FixedPointMathLib.sol | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index 63db5285..66891bc2 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -165,18 +165,13 @@ library FixedPointMathLib { function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { - z := 181 // The "correct" value is 1, but this saves a multiplication later. + let y := x // We start y at x, which will help us make our initial estimate. - let y := x + z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. - // Goal is to get z*z*y within a small factor of x. More iterations will - // get y in a tighter range. Currently, we will have y in [256, 256*2^16). - // We ensure y >= 256 so that the relative difference between y and y+1 is small. - // That's not possible if x < 256 but we can just verify those cases exhaustively. - // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { @@ -196,15 +191,20 @@ library FixedPointMathLib { z := shl(8, z) } + // Goal was to get z*z*y within a small factor of x. More iterations could + // get y in a tighter range. Currently, we will have y in [256, 256*2^16). + // We ensured y >= 256 so that the relative difference between y and y+1 is small. + // That's not possible if x < 256 but we can just verify those cases exhaustively. + // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. - // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) - // is in the range (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 - // and when s = 256 or 1/256. Since y is in [256, 256*2^16), let a = y/65536, so - // that a is in [1/256, 256). Then we can estimate sqrt(y) as - // sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18 + // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range + // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. + + // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate + // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. @@ -221,7 +221,7 @@ library FixedPointMathLib { // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This check ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division - // Since this case is rare, we save gas on the assignment and repeat division in the rare case. + // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this block. if lt(div(x, z), z) { z := div(x, z) From 43c2fdf049f50b3c9f06096de81e367e21e3f4d2 Mon Sep 17 00:00:00 2001 From: t11s Date: Fri, 13 May 2022 08:22:33 -0700 Subject: [PATCH 14/44] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/ERC1155B.t.sol | 933 -------------------------------- src/utils/FixedPointMathLib.sol | 1 - 2 files changed, 934 deletions(-) diff --git a/src/test/ERC1155B.t.sol b/src/test/ERC1155B.t.sol index 1dc3aca4..403837c8 100644 --- a/src/test/ERC1155B.t.sol +++ b/src/test/ERC1155B.t.sol @@ -659,937 +659,4 @@ contract ERC1155BTest is DSTestPlus, ERC1155TokenReceiver { token.balanceOfBatch(tos, ids); } - - // function testMintToEOA( - // address to, - // uint256 id, - // uint256 amount, - // bytes memory mintData - // ) public { - // if (to == address(0)) to = address(0xBEEF); - - // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; - - // token.mint(to, id, amount, mintData); - - // assertEq(token.balanceOf(to, id), amount); - // } - - // function testMintToERC1155Recipient( - // uint256 id, - // uint256 amount, - // bytes memory mintData - // ) public { - // ERC1155BRecipient to = new ERC1155BRecipient(); - - // token.mint(address(to), id, amount, mintData); - - // assertEq(token.balanceOf(address(to), id), amount); - - // assertEq(to.operator(), address(this)); - // assertEq(to.from(), address(0)); - // assertEq(to.id(), id); - // assertBytesEq(to.mintData(), mintData); - // } - - // function testBatchMintToEOA( - // address to, - // uint256[] memory ids, - // uint256[] memory amounts, - // bytes memory mintData - // ) public { - // if (to == address(0)) to = address(0xBEEF); - - // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; - - // uint256 minLength = min2(ids.length, amounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[to][id]; - - // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); - - // normalizedIds[i] = id; - // normalizedAmounts[i] = mintAmount; - - // userMintAmounts[to][id] += mintAmount; - // } - - // token.batchMint(to, normalizedIds, normalizedAmounts, mintData); - - // for (uint256 i = 0; i < normalizedIds.length; i++) { - // uint256 id = normalizedIds[i]; - - // assertEq(token.balanceOf(to, id), userMintAmounts[to][id]); - // } - // } - - // function testBatchMintToERC1155Recipient( - // uint256[] memory ids, - // uint256[] memory amounts, - // bytes memory mintData - // ) public { - // ERC1155BRecipient to = new ERC1155BRecipient(); - - // uint256 minLength = min2(ids.length, amounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; - - // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); - - // normalizedIds[i] = id; - // normalizedAmounts[i] = mintAmount; - - // userMintAmounts[address(to)][id] += mintAmount; - // } - - // token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); - - // assertEq(to.batchOperator(), address(this)); - // assertEq(to.batchFrom(), address(0)); - // assertUintArrayEq(to.batchIds(), normalizedIds); - // assertUintArrayEq(to.batchAmounts(), normalizedAmounts); - // assertBytesEq(to.batchData(), mintData); - - // for (uint256 i = 0; i < normalizedIds.length; i++) { - // uint256 id = normalizedIds[i]; - - // assertEq(token.balanceOf(address(to), id), userMintAmounts[address(to)][id]); - // } - // } - - // function testBurn( - // address to, - // uint256 id, - // uint256 mintAmount, - // bytes memory mintData, - // uint256 burnAmount - // ) public { - // if (to == address(0)) to = address(0xBEEF); - - // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; - - // burnAmount = bound(burnAmount, 0, mintAmount); - - // token.mint(to, id, mintAmount, mintData); - - // token.burn(to, id, burnAmount); - - // assertEq(token.balanceOf(address(to), id), mintAmount - burnAmount); - // } - - // function testBatchBurn( - // address to, - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory burnAmounts, - // bytes memory mintData - // ) public { - // if (to == address(0)) to = address(0xBEEF); - - // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; - - // uint256 minLength = min3(ids.length, mintAmounts.length, burnAmounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedBurnAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = bound(mintAmounts[i], 0, remainingMintAmountForId); - // normalizedBurnAmounts[i] = bound(burnAmounts[i], 0, normalizedMintAmounts[i]); - - // userMintAmounts[address(to)][id] += normalizedMintAmounts[i]; - // userTransferOrBurnAmounts[address(to)][id] += normalizedBurnAmounts[i]; - // } - - // token.batchMint(to, normalizedIds, normalizedMintAmounts, mintData); - - // token.batchBurn(to, normalizedIds, normalizedBurnAmounts); - - // for (uint256 i = 0; i < normalizedIds.length; i++) { - // uint256 id = normalizedIds[i]; - - // assertEq(token.balanceOf(to, id), userMintAmounts[to][id] - userTransferOrBurnAmounts[to][id]); - // } - // } - - // function testApproveAll(address to, bool approved) public { - // token.setApprovalForAll(to, approved); - - // assertBoolEq(token.isApprovedForAll(address(this), to), approved); - // } - - // function testSafeTransferFromToEOA( - // uint256 id, - // uint256 mintAmount, - // bytes memory mintData, - // uint256 transferAmount, - // address to, - // bytes memory transferData - // ) public { - // if (to == address(0)) to = address(0xBEEF); - - // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; - - // transferAmount = bound(transferAmount, 0, mintAmount); - - // ERC1155BUser from = new ERC1155BUser(token); - - // token.mint(address(from), id, mintAmount, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeTransferFrom(address(from), to, id, transferAmount, transferData); - - // assertEq(token.balanceOf(to, id), transferAmount); - // assertEq(token.balanceOf(address(from), id), mintAmount - transferAmount); - // } - - // function testSafeTransferFromToERC1155Recipient( - // uint256 id, - // uint256 mintAmount, - // bytes memory mintData, - // uint256 transferAmount, - // bytes memory transferData - // ) public { - // ERC1155BRecipient to = new ERC1155BRecipient(); - - // ERC1155BUser from = new ERC1155BUser(token); - - // transferAmount = bound(transferAmount, 0, mintAmount); - - // token.mint(address(from), id, mintAmount, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeTransferFrom(address(from), address(to), id, transferAmount, transferData); - - // assertEq(to.operator(), address(this)); - // assertEq(to.from(), address(from)); - // assertEq(to.id(), id); - // assertBytesEq(to.mintData(), transferData); - - // assertEq(token.balanceOf(address(to), id), transferAmount); - // assertEq(token.balanceOf(address(from), id), mintAmount - transferAmount); - // } - - // function testSafeTransferFromSelf( - // uint256 id, - // uint256 mintAmount, - // bytes memory mintData, - // uint256 transferAmount, - // address to, - // bytes memory transferData - // ) public { - // if (to == address(0)) to = address(0xBEEF); - - // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; - - // transferAmount = bound(transferAmount, 0, mintAmount); - - // token.mint(address(this), id, mintAmount, mintData); - - // token.safeTransferFrom(address(this), to, id, transferAmount, transferData); - - // assertEq(token.balanceOf(to, id), transferAmount); - // assertEq(token.balanceOf(address(this), id), mintAmount - transferAmount); - // } - - // function testSafeBatchTransferFromToEOA( - // address to, - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory transferAmounts, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // if (to == address(0)) to = address(0xBEEF); - - // if (uint256(uint160(to)) <= 18 || to.code.length > 0) return; - - // ERC1155BUser from = new ERC1155BUser(token); - - // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; - - // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); - // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = mintAmount; - // normalizedTransferAmounts[i] = transferAmount; - - // userMintAmounts[address(from)][id] += mintAmount; - // userTransferOrBurnAmounts[address(from)][id] += transferAmount; - // } - - // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeBatchTransferFrom(address(from), to, normalizedIds, normalizedTransferAmounts, transferData); - - // for (uint256 i = 0; i < normalizedIds.length; i++) { - // uint256 id = normalizedIds[i]; - - // assertEq(token.balanceOf(address(to), id), userTransferOrBurnAmounts[address(from)][id]); - // assertEq( - // token.balanceOf(address(from), id), - // userMintAmounts[address(from)][id] - userTransferOrBurnAmounts[address(from)][id] - // ); - // } - // } - - // function testSafeBatchTransferFromToERC1155Recipient( - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory transferAmounts, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // ERC1155BUser from = new ERC1155BUser(token); - - // ERC1155BRecipient to = new ERC1155BRecipient(); - - // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; - - // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); - // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = mintAmount; - // normalizedTransferAmounts[i] = transferAmount; - - // userMintAmounts[address(from)][id] += mintAmount; - // userTransferOrBurnAmounts[address(from)][id] += transferAmount; - // } - - // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeBatchTransferFrom(address(from), address(to), normalizedIds, normalizedTransferAmounts, transferData); - - // assertEq(to.batchOperator(), address(this)); - // assertEq(to.batchFrom(), address(from)); - // assertUintArrayEq(to.batchIds(), normalizedIds); - // assertUintArrayEq(to.batchAmounts(), normalizedTransferAmounts); - // assertBytesEq(to.batchData(), transferData); - - // for (uint256 i = 0; i < normalizedIds.length; i++) { - // uint256 id = normalizedIds[i]; - // uint256 transferAmount = userTransferOrBurnAmounts[address(from)][id]; - - // assertEq(token.balanceOf(address(to), id), transferAmount); - // assertEq(token.balanceOf(address(from), id), userMintAmounts[address(from)][id] - transferAmount); - // } - // } - - // function testBatchBalanceOf( - // address[] memory tos, - // uint256[] memory ids, - // uint256[] memory amounts, - // bytes memory mintData - // ) public { - // uint256 minLength = min3(tos.length, ids.length, amounts.length); - - // address[] memory normalizedTos = new address[](minLength); - // uint256[] memory normalizedIds = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - // address to = tos[i] == address(0) ? address(0xBEEF) : tos[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[to][id]; - - // normalizedTos[i] = to; - // normalizedIds[i] = id; - - // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); - - // token.mint(to, id, mintAmount, mintData); - - // userMintAmounts[to][id] += mintAmount; - // } - - // uint256[] memory balances = token.balanceOfBatch(normalizedTos, normalizedIds); - - // for (uint256 i = 0; i < normalizedTos.length; i++) { - // assertEq(balances[i], token.balanceOf(normalizedTos[i], normalizedIds[i])); - // } - // } - - // function testFailMintToZero( - // uint256 id, - // uint256 amount, - // bytes memory data - // ) public { - // token.mint(address(0), id, amount, data); - // } - - // function testFailMintToNonERC1155Recipient( - // uint256 id, - // uint256 mintAmount, - // bytes memory mintData - // ) public { - // token.mint(address(new NonERC1155BRecipient()), id, mintAmount, mintData); - // } - - // function testFailMintToRevertingERC1155Recipient( - // uint256 id, - // uint256 mintAmount, - // bytes memory mintData - // ) public { - // token.mint(address(new RevertingERC1155Recipient()), id, mintAmount, mintData); - // } - - // function testFailMintToWrongReturnDataERC1155Recipient( - // uint256 id, - // uint256 mintAmount, - // bytes memory mintData - // ) public { - // token.mint(address(new RevertingERC1155Recipient()), id, mintAmount, mintData); - // } - - // function testFailBurnInsufficientBalance( - // address to, - // uint256 id, - // uint256 mintAmount, - // uint256 burnAmount, - // bytes memory mintData - // ) public { - // burnAmount = bound(burnAmount, mintAmount + 1, type(uint256).max); - - // token.mint(to, id, mintAmount, mintData); - // token.burn(to, id, burnAmount); - // } - - // function testFailSafeTransferFromInsufficientBalance( - // address to, - // uint256 id, - // uint256 mintAmount, - // uint256 transferAmount, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // ERC1155BUser from = new ERC1155BUser(token); - - // transferAmount = bound(transferAmount, mintAmount + 1, type(uint256).max); - - // token.mint(address(from), id, mintAmount, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeTransferFrom(address(from), to, id, transferAmount, transferData); - // } - - // function testFailSafeTransferFromSelfInsufficientBalance( - // address to, - // uint256 id, - // uint256 mintAmount, - // uint256 transferAmount, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // transferAmount = bound(transferAmount, mintAmount + 1, type(uint256).max); - - // token.mint(address(this), id, mintAmount, mintData); - // token.safeTransferFrom(address(this), to, id, transferAmount, transferData); - // } - - // function testFailSafeTransferFromToZero( - // uint256 id, - // uint256 mintAmount, - // uint256 transferAmount, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // transferAmount = bound(transferAmount, 0, mintAmount); - - // token.mint(address(this), id, mintAmount, mintData); - // token.safeTransferFrom(address(this), address(0), id, transferAmount, transferData); - // } - - // function testFailSafeTransferFromToNonERC1155Recipient( - // uint256 id, - // uint256 mintAmount, - // uint256 transferAmount, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // transferAmount = bound(transferAmount, 0, mintAmount); - - // token.mint(address(this), id, mintAmount, mintData); - // token.safeTransferFrom(address(this), address(new NonERC1155BRecipient()), id, transferAmount, transferData); - // } - - // function testFailSafeTransferFromToRevertingERC1155Recipient( - // uint256 id, - // uint256 mintAmount, - // uint256 transferAmount, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // transferAmount = bound(transferAmount, 0, mintAmount); - - // token.mint(address(this), id, mintAmount, mintData); - // token.safeTransferFrom( - // address(this), - // address(new RevertingERC1155Recipient()), - // id, - // transferAmount, - // transferData - // ); - // } - - // function testFailSafeTransferFromToWrongReturnDataERC1155Recipient( - // uint256 id, - // uint256 mintAmount, - // uint256 transferAmount, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // transferAmount = bound(transferAmount, 0, mintAmount); - - // token.mint(address(this), id, mintAmount, mintData); - // token.safeTransferFrom( - // address(this), - // address(new WrongReturnDataERC1155BRecipient()), - // id, - // transferAmount, - // transferData - // ); - // } - - // function testFailSafeBatchTransferInsufficientBalance( - // address to, - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory transferAmounts, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // ERC1155BUser from = new ERC1155BUser(token); - - // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); - - // if (minLength == 0) revert(); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; - - // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); - // uint256 transferAmount = bound(transferAmounts[i], mintAmount + 1, type(uint256).max); - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = mintAmount; - // normalizedTransferAmounts[i] = transferAmount; - - // userMintAmounts[address(from)][id] += mintAmount; - // } - - // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeBatchTransferFrom(address(from), to, normalizedIds, normalizedTransferAmounts, transferData); - // } - - // function testFailSafeBatchTransferFromToZero( - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory transferAmounts, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // ERC1155BUser from = new ERC1155BUser(token); - - // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; - - // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); - // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = mintAmount; - // normalizedTransferAmounts[i] = transferAmount; - - // userMintAmounts[address(from)][id] += mintAmount; - // } - - // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeBatchTransferFrom(address(from), address(0), normalizedIds, normalizedTransferAmounts, transferData); - // } - - // function testFailSafeBatchTransferFromToNonERC1155Recipient( - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory transferAmounts, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // ERC1155BUser from = new ERC1155BUser(token); - - // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; - - // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); - // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = mintAmount; - // normalizedTransferAmounts[i] = transferAmount; - - // userMintAmounts[address(from)][id] += mintAmount; - // } - - // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeBatchTransferFrom( - // address(from), - // address(new NonERC1155BRecipient()), - // normalizedIds, - // normalizedTransferAmounts, - // transferData - // ); - // } - - // function testFailSafeBatchTransferFromToRevertingERC1155Recipient( - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory transferAmounts, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // ERC1155BUser from = new ERC1155BUser(token); - - // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; - - // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); - // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = mintAmount; - // normalizedTransferAmounts[i] = transferAmount; - - // userMintAmounts[address(from)][id] += mintAmount; - // } - - // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeBatchTransferFrom( - // address(from), - // address(new RevertingERC1155Recipient()), - // normalizedIds, - // normalizedTransferAmounts, - // transferData - // ); - // } - - // function testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient( - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory transferAmounts, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // ERC1155BUser from = new ERC1155BUser(token); - - // uint256 minLength = min3(ids.length, mintAmounts.length, transferAmounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedTransferAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(from)][id]; - - // uint256 mintAmount = bound(mintAmounts[i], 0, remainingMintAmountForId); - // uint256 transferAmount = bound(transferAmounts[i], 0, mintAmount); - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = mintAmount; - // normalizedTransferAmounts[i] = transferAmount; - - // userMintAmounts[address(from)][id] += mintAmount; - // } - - // token.batchMint(address(from), normalizedIds, normalizedMintAmounts, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeBatchTransferFrom( - // address(from), - // address(new WrongReturnDataERC1155BRecipient()), - // normalizedIds, - // normalizedTransferAmounts, - // transferData - // ); - // } - - // function testFailSafeBatchTransferFromWithArrayLengthMismatch( - // address to, - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory transferAmounts, - // bytes memory mintData, - // bytes memory transferData - // ) public { - // ERC1155BUser from = new ERC1155BUser(token); - - // if (ids.length == transferAmounts.length) revert(); - - // token.batchMint(address(from), ids, mintAmounts, mintData); - - // from.setApprovalForAll(address(this), true); - - // token.safeBatchTransferFrom(address(from), to, ids, transferAmounts, transferData); - // } - - // function testFailBatchMintToZero( - // uint256[] memory ids, - // uint256[] memory amounts, - // bytes memory mintData - // ) public { - // uint256 minLength = min2(ids.length, amounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(0)][id]; - - // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); - - // normalizedIds[i] = id; - // normalizedAmounts[i] = mintAmount; - - // userMintAmounts[address(0)][id] += mintAmount; - // } - - // token.batchMint(address(0), normalizedIds, normalizedAmounts, mintData); - // } - - // function testFailBatchMintToNonERC1155Recipient( - // uint256[] memory ids, - // uint256[] memory amounts, - // bytes memory mintData - // ) public { - // NonERC1155BRecipient to = new NonERC1155BRecipient(); - - // uint256 minLength = min2(ids.length, amounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; - - // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); - - // normalizedIds[i] = id; - // normalizedAmounts[i] = mintAmount; - - // userMintAmounts[address(to)][id] += mintAmount; - // } - - // token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); - // } - - // function testFailBatchMintToRevertingERC1155Recipient( - // uint256[] memory ids, - // uint256[] memory amounts, - // bytes memory mintData - // ) public { - // RevertingERC1155Recipient to = new RevertingERC1155Recipient(); - - // uint256 minLength = min2(ids.length, amounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; - - // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); - - // normalizedIds[i] = id; - // normalizedAmounts[i] = mintAmount; - - // userMintAmounts[address(to)][id] += mintAmount; - // } - - // token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); - // } - - // function testFailBatchMintToWrongReturnDataERC1155Recipient( - // uint256[] memory ids, - // uint256[] memory amounts, - // bytes memory mintData - // ) public { - // WrongReturnDataERC1155BRecipient to = new WrongReturnDataERC1155BRecipient(); - - // uint256 minLength = min2(ids.length, amounts.length); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[address(to)][id]; - - // uint256 mintAmount = bound(amounts[i], 0, remainingMintAmountForId); - - // normalizedIds[i] = id; - // normalizedAmounts[i] = mintAmount; - - // userMintAmounts[address(to)][id] += mintAmount; - // } - - // token.batchMint(address(to), normalizedIds, normalizedAmounts, mintData); - // } - - // function testFailBatchMintWithArrayMismatch( - // address to, - // uint256[] memory ids, - // uint256[] memory amounts, - // bytes memory mintData - // ) public { - // if (ids.length == amounts.length) revert(); - - // token.batchMint(address(to), ids, amounts, mintData); - // } - - // function testFailBatchBurnInsufficientBalance( - // address to, - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory burnAmounts, - // bytes memory mintData - // ) public { - // uint256 minLength = min3(ids.length, mintAmounts.length, burnAmounts.length); - - // if (minLength == 0) revert(); - - // uint256[] memory normalizedIds = new uint256[](minLength); - // uint256[] memory normalizedMintAmounts = new uint256[](minLength); - // uint256[] memory normalizedBurnAmounts = new uint256[](minLength); - - // for (uint256 i = 0; i < minLength; i++) { - // uint256 id = ids[i]; - - // uint256 remainingMintAmountForId = type(uint256).max - userMintAmounts[to][id]; - - // normalizedIds[i] = id; - // normalizedMintAmounts[i] = bound(mintAmounts[i], 0, remainingMintAmountForId); - // normalizedBurnAmounts[i] = bound(burnAmounts[i], normalizedMintAmounts[i] + 1, type(uint256).max); - - // userMintAmounts[to][id] += normalizedMintAmounts[i]; - // } - - // token.batchMint(to, normalizedIds, normalizedMintAmounts, mintData); - - // token.batchBurn(to, normalizedIds, normalizedBurnAmounts); - // } - - // function testFailBatchBurnWithArrayLengthMismatch( - // address to, - // uint256[] memory ids, - // uint256[] memory mintAmounts, - // uint256[] memory burnAmounts, - // bytes memory mintData - // ) public { - // if (ids.length == burnAmounts.length) revert(); - - // token.batchMint(to, ids, mintAmounts, mintData); - - // token.batchBurn(to, ids, burnAmounts); - // } - - // function testFailBalanceOfBatchWithArrayMismatch(address[] memory tos, uint256[] memory ids) public view { - // if (tos.length == ids.length) revert(); - - // token.balanceOfBatch(tos, ids); - // } } diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index 8ec3943d..8311a952 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -5,7 +5,6 @@ import {BitwiseLib} from "./BitwiseLib.sol"; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) -/// @author Inspired by Balancer (https://github.com/balancer-labs/balancer-v2-monorepo/tree/master/pkg/solidity-utils/contracts/math) library FixedPointMathLib { error Overflow(); From 234f5fcfda5fcdd0e83555c821938f1e13d17645 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Fri, 13 May 2022 10:38:21 -0700 Subject: [PATCH 15/44] Remco/zero to one (#231) --- src/test/FixedPointMathLib.t.sol | 32 ++++++++++++++++++-------------- src/utils/FixedPointMathLib.sol | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/test/FixedPointMathLib.t.sol b/src/test/FixedPointMathLib.t.sol index e7119805..159cd32b 100644 --- a/src/test/FixedPointMathLib.t.sol +++ b/src/test/FixedPointMathLib.t.sol @@ -16,41 +16,45 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.expWad(-0.5e18), 606530659712633423); assertEq(FixedPointMathLib.expWad(-0.3e18), 740818220681717866); - assertEq( - FixedPointMathLib.expWad(0), - 999999999999999999 - // True value: 1000000000000000000 (off by 1 wei) - ); + assertEq(FixedPointMathLib.expWad(0), 1000000000000000000); assertEq(FixedPointMathLib.expWad(0.3e18), 1349858807576003103); assertEq(FixedPointMathLib.expWad(0.5e18), 1648721270700128146); assertEq(FixedPointMathLib.expWad(1e18), 2718281828459045235); assertEq(FixedPointMathLib.expWad(2e18), 7389056098930650227); - assertEq(FixedPointMathLib.expWad(3e18), 20085536923187667740); + assertEq( + FixedPointMathLib.expWad(3e18), + 20085536923187667741 + // True value: 20085536923187667740.92 + ); assertEq( FixedPointMathLib.expWad(10e18), - 22026465794806716516_861 - // True value: 22026465794806716516_957 (21 digits of precision) + 220264657948067165169_80 + // True value: 22026465794806716516957.90 + // Relative error 9.987984547746668e-22 ); assertEq( FixedPointMathLib.expWad(50e18), - 5184705528587072464_117909654408922782335 - // True value: 5184705528587072464_087453322933485384827 (19 digits of precision) + 5184705528587072464_148529318587763226117 + // True value: 5184705528587072464_087453322933485384827.47 + // Relative error: 1.1780031733243328e-20 ); assertEq( FixedPointMathLib.expWad(100e18), - 2688117141816135448_3982463551405023462056137701762092799015183 - // True value: 2688117141816135448_4126255515800135873611118773741922415191608 (20 digits of precision) + 268811714181613544841_34666106240937146178367581647816351662017 + // True value: 268811714181613544841_26255515800135873611118773741922415191608 + // Relative error: 3.128803544297531e-22 ); assertEq( FixedPointMathLib.expWad(135305999368893231588), - 578960446186580976498_09650847705537384645150747719143657509713249170749644355 - // True value: 578960446186580976498_16762928942336782129491980154662247847962410455084893091 (21 digits of precision) + 578960446186580976_50144101621524338577433870140581303254786265309376407432913 + // True value: 578960446186580976_49816762928942336782129491980154662247847962410455084893091 + // Relative error: 5.653904247484822e-21 ); } diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index 8311a952..d18f928f 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -61,7 +61,7 @@ library FixedPointMathLib { y = ((y * x) >> 96) + 57155421227552351082224309758442; int256 p = y + x - 94201549194550492254356042504812; p = ((p * y) >> 96) + 28719021644029726153956944680412240; - p = p * x + (4385272521454847904632057985693276 << 96); + p = p * x + (4385272521454847904659076985693276 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. int256 q = x - 2855989394907223263936484059900; From d7f03abe94c51be3189014c8bdb89aa9bac14139 Mon Sep 17 00:00:00 2001 From: Pranay Date: Mon, 16 May 2022 09:41:05 +0530 Subject: [PATCH 16/44] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Optimize=20ERC-1155?= =?UTF-8?q?=20JUMPs=20(#237)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Optimize ERC-1155 JUMPs * ♻️ Cleanup * 📝 Dead comment Co-authored-by: t11s --- .gas-snapshot | 80 ++++++++++++++++++++--------------------- src/tokens/ERC1155.sol | 48 ++++++++++++------------- src/tokens/ERC1155B.sol | 48 ++++++++++++------------- 3 files changed, 88 insertions(+), 88 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 81f3e833..420d5b37 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -25,79 +25,79 @@ DSTestPlusTest:testFailBoundMinBiggerThanMax() (gas: 287) DSTestPlusTest:testMeasuringGas() (gas: 24600) DSTestPlusTest:testRelApproxEqBothZeroesPasses() (gas: 391) ERC1155Test:testApproveAll() (gas: 31053) -ERC1155Test:testBatchBalanceOf() (gas: 157587) -ERC1155Test:testBatchBurn() (gas: 151051) -ERC1155Test:testBatchMintToEOA() (gas: 137293) +ERC1155Test:testBatchBalanceOf() (gas: 157552) +ERC1155Test:testBatchBurn() (gas: 151044) +ERC1155Test:testBatchMintToEOA() (gas: 137286) ERC1155Test:testBatchMintToERC1155Recipient() (gas: 942660) -ERC1155Test:testBurn() (gas: 38576) +ERC1155Test:testBurn() (gas: 38569) ERC1155Test:testFailBalanceOfBatchWithArrayMismatch() (gas: 7933) -ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136177) -ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 135543) +ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136170) +ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 135536) ERC1155Test:testFailBatchMintToNonERC1155Recipient() (gas: 167311) ERC1155Test:testFailBatchMintToRevertingERC1155Recipient() (gas: 358854) -ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 310745) -ERC1155Test:testFailBatchMintToZero() (gas: 131716) +ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 310733) +ERC1155Test:testFailBatchMintToZero() (gas: 131709) ERC1155Test:testFailBatchMintWithArrayMismatch() (gas: 9621) -ERC1155Test:testFailBurnInsufficientBalance() (gas: 34830) +ERC1155Test:testFailBurnInsufficientBalance() (gas: 34823) ERC1155Test:testFailMintToNonERC155Recipient() (gas: 68192) ERC1155Test:testFailMintToRevertingERC155Recipient() (gas: 259413) ERC1155Test:testFailMintToWrongReturnDataERC155Recipient() (gas: 259412) -ERC1155Test:testFailMintToZero() (gas: 33705) -ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 321355) -ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 512934) -ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 464869) -ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 286535) -ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 162653) -ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 163533) -ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 63267) +ERC1155Test:testFailMintToZero() (gas: 33698) +ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 321348) +ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 512927) +ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 464850) +ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 286521) +ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 162646) +ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 163526) +ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 63260) ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance() (gas: 34320) ERC1155Test:testFailSafeTransferFromToNonERC155Recipient() (gas: 96510) ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 287732) -ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 239610) -ERC1155Test:testFailSafeTransferFromToZero() (gas: 62014) -ERC1155Test:testMintToEOA() (gas: 34743) +ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 239598) +ERC1155Test:testFailSafeTransferFromToZero() (gas: 62007) +ERC1155Test:testMintToEOA() (gas: 34736) ERC1155Test:testMintToERC1155Recipient() (gas: 608327) -ERC1155Test:testSafeBatchTransferFromToEOA() (gas: 297822) -ERC1155Test:testSafeBatchTransferFromToERC1155Recipient() (gas: 1122274) -ERC1155Test:testSafeTransferFromSelf() (gas: 64155) -ERC1155Test:testSafeTransferFromToEOA() (gas: 93168) -ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 686500) +ERC1155Test:testSafeBatchTransferFromToEOA() (gas: 297808) +ERC1155Test:testSafeBatchTransferFromToERC1155Recipient() (gas: 1122267) +ERC1155Test:testSafeTransferFromSelf() (gas: 64148) +ERC1155Test:testSafeTransferFromToEOA() (gas: 93154) +ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 686493) ERC1155BTest:testApproveAll() (gas: 30947) -ERC1155BTest:testBatchBalanceOf() (gas: 157240) +ERC1155BTest:testBatchBalanceOf() (gas: 157205) ERC1155BTest:testBatchBurn() (gas: 114460) ERC1155BTest:testBatchMintToEOA() (gas: 135755) ERC1155BTest:testBatchMintToERC1155Recipient() (gas: 941538) -ERC1155BTest:testBurn() (gas: 26508) +ERC1155BTest:testBurn() (gas: 26502) ERC1155BTest:testFailBalanceOfBatchWithArrayMismatch() (gas: 7933) ERC1155BTest:testFailBatchBurnInsufficientBalance() (gas: 10052) ERC1155BTest:testFailBatchMintToNonERC1155Recipient() (gas: 166023) ERC1155BTest:testFailBatchMintToRevertingERC1155Recipient() (gas: 357584) -ERC1155BTest:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 309471) +ERC1155BTest:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 309459) ERC1155BTest:testFailBatchMintToZero() (gas: 30941) ERC1155BTest:testFailBurnInsufficientBalance() (gas: 7768) ERC1155BTest:testFailMintToNonERC1155Recipient() (gas: 68217) ERC1155BTest:testFailMintToRevertingERC1155Recipient() (gas: 259420) ERC1155BTest:testFailMintToWrongReturnDataERC1155Recipient() (gas: 259419) -ERC1155BTest:testFailMintToZero() (gas: 13766) +ERC1155BTest:testFailMintToZero() (gas: 13759) ERC1155BTest:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 722319) ERC1155BTest:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 913812) -ERC1155BTest:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 865743) -ERC1155BTest:testFailSafeBatchTransferFromToZero() (gas: 687476) +ERC1155BTest:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 865731) +ERC1155BTest:testFailSafeBatchTransferFromToZero() (gas: 687469) ERC1155BTest:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 674842) ERC1155BTest:testFailSafeBatchTransferInsufficientBalance() (gas: 552088) ERC1155BTest:testFailSafeTransferFromInsufficientBalance() (gas: 549469) ERC1155BTest:testFailSafeTransferFromSelfInsufficientBalance() (gas: 8381) -ERC1155BTest:testFailSafeTransferFromToNonERC1155Recipient() (gas: 74204) -ERC1155BTest:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 265404) -ERC1155BTest:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 217275) +ERC1155BTest:testFailSafeTransferFromToNonERC1155Recipient() (gas: 74192) +ERC1155BTest:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 265392) +ERC1155BTest:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 217251) ERC1155BTest:testFailSafeTransferFromToZero() (gas: 8362) -ERC1155BTest:testMintToEOA() (gas: 34642) -ERC1155BTest:testMintToERC1155Recipient() (gas: 608200) -ERC1155BTest:testSafeBatchTransferFromToEOA() (gas: 698170) +ERC1155BTest:testMintToEOA() (gas: 34635) +ERC1155BTest:testMintToERC1155Recipient() (gas: 608188) +ERC1155BTest:testSafeBatchTransferFromToEOA() (gas: 698163) ERC1155BTest:testSafeBatchTransferFromToERC1155Recipient() (gas: 1522381) -ERC1155BTest:testSafeTransferFromSelf() (gas: 41780) -ERC1155BTest:testSafeTransferFromToEOA() (gas: 582836) -ERC1155BTest:testSafeTransferFromToERC1155Recipient() (gas: 1175937) +ERC1155BTest:testSafeTransferFromSelf() (gas: 41761) +ERC1155BTest:testSafeTransferFromToEOA() (gas: 582817) +ERC1155BTest:testSafeTransferFromToERC1155Recipient() (gas: 1175925) ERC20Test:testApprove() (gas: 31080) ERC20Test:testBurn() (gas: 57014) ERC20Test:testFailPermitBadDeadline() (gas: 36924) diff --git a/src/tokens/ERC1155.sol b/src/tokens/ERC1155.sol index 70c4d2d0..df0aa1ae 100644 --- a/src/tokens/ERC1155.sol +++ b/src/tokens/ERC1155.sol @@ -66,13 +66,13 @@ abstract contract ERC1155 { emit TransferSingle(msg.sender, from, to, id, amount); - require( - to.code.length == 0 - ? to != address(0) - : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == + if (to.code.length != 0) { + require( + ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, - "UNSAFE_RECIPIENT" - ); + "UNSAFE_RECIPIENT" + ); + } else require(to != address(0), "INVALID_RECIPIENT"); } function safeBatchTransferFrom( @@ -106,13 +106,13 @@ abstract contract ERC1155 { emit TransferBatch(msg.sender, from, to, ids, amounts); - require( - to.code.length == 0 - ? to != address(0) - : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == + if (to.code.length != 0) { + require( + ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, - "UNSAFE_RECIPIENT" - ); + "UNSAFE_RECIPIENT" + ); + } else require(to != address(0), "INVALID_RECIPIENT"); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) @@ -159,13 +159,13 @@ abstract contract ERC1155 { emit TransferSingle(msg.sender, address(0), to, id, amount); - require( - to.code.length == 0 - ? to != address(0) - : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == + if (to.code.length != 0) { + require( + ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, - "UNSAFE_RECIPIENT" - ); + "UNSAFE_RECIPIENT" + ); + } else require(to != address(0), "INVALID_RECIPIENT"); } function _batchMint( @@ -190,13 +190,13 @@ abstract contract ERC1155 { emit TransferBatch(msg.sender, address(0), to, ids, amounts); - require( - to.code.length == 0 - ? to != address(0) - : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == + if (to.code.length != 0) { + require( + ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, - "UNSAFE_RECIPIENT" - ); + "UNSAFE_RECIPIENT" + ); + } else require(to != address(0), "INVALID_RECIPIENT"); } function _batchBurn( diff --git a/src/tokens/ERC1155B.sol b/src/tokens/ERC1155B.sol index 6e407da8..ddb3a44f 100644 --- a/src/tokens/ERC1155B.sol +++ b/src/tokens/ERC1155B.sol @@ -86,13 +86,13 @@ abstract contract ERC1155B { emit TransferSingle(msg.sender, from, to, id, amount); - require( - to.code.length == 0 - ? to != address(0) - : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == + if (to.code.length != 0) { + require( + ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, - "UNSAFE_RECIPIENT" - ); + "UNSAFE_RECIPIENT" + ); + } else require(to != address(0), "INVALID_RECIPIENT"); } function safeBatchTransferFrom( @@ -129,13 +129,13 @@ abstract contract ERC1155B { emit TransferBatch(msg.sender, from, to, ids, amounts); - require( - to.code.length == 0 - ? to != address(0) - : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == + if (to.code.length != 0) { + require( + ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, - "UNSAFE_RECIPIENT" - ); + "UNSAFE_RECIPIENT" + ); + } else require(to != address(0), "INVALID_RECIPIENT"); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) @@ -173,13 +173,13 @@ abstract contract ERC1155B { emit TransferSingle(msg.sender, address(0), to, id, 1); - require( - to.code.length == 0 - ? to != address(0) - : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, 1, data) == + if (to.code.length != 0) { + require( + ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, 1, data) == ERC1155TokenReceiver.onERC1155Received.selector, - "UNSAFE_RECIPIENT" - ); + "UNSAFE_RECIPIENT" + ); + } else require(to != address(0), "INVALID_RECIPIENT"); } function _batchMint( @@ -211,13 +211,13 @@ abstract contract ERC1155B { emit TransferBatch(msg.sender, address(0), to, ids, amounts); - require( - to.code.length == 0 - ? to != address(0) - : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == + if (to.code.length != 0) { + require( + ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, - "UNSAFE_RECIPIENT" - ); + "UNSAFE_RECIPIENT" + ); + } else require(to != address(0), "INVALID_RECIPIENT"); } function _batchBurn(address from, uint256[] memory ids) internal virtual { From 0303df878f4fbb96678d64026bb9cf27190f890b Mon Sep 17 00:00:00 2001 From: UncleGrandpa925 Date: Wed, 18 May 2022 07:57:44 +0800 Subject: [PATCH 17/44] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Add=20missing=20pure?= =?UTF-8?q?=20modifiers=20to=20math=20functions=20(#235)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/BitwiseLib.sol | 2 +- src/utils/FixedPointMathLib.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/BitwiseLib.sol b/src/utils/BitwiseLib.sol index 7feb3e4c..3593f537 100644 --- a/src/utils/BitwiseLib.sol +++ b/src/utils/BitwiseLib.sol @@ -9,7 +9,7 @@ library BitwiseLib { // @returns floor(log2(x)) if x is nonzero, otherwise 0. // This is the same as the location of the highest set bit. // Consumes 232 gas. This could have been an 3 gas EVM opcode though. - function ilog2(uint256 x) internal returns (uint256 r) { + function ilog2(uint256 x) internal pure returns (uint256 r) { assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index d18f928f..163f1bb1 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -97,7 +97,7 @@ library FixedPointMathLib { // reverts with `LnNegativeUndefined()` if x is negative, and with // `Overflow()` if x is zero. // Consumes about 670 gas. - function lnWad(int256 x) internal returns (int256 r) { + function lnWad(int256 x) internal pure returns (int256 r) { unchecked { if (x < 1) { if (x < 0) revert LnNegativeUndefined(); From f759f5d483d403c4dd10de005a92d17bde4ba504 Mon Sep 17 00:00:00 2001 From: t11s Date: Tue, 17 May 2022 17:03:40 -0700 Subject: [PATCH 18/44] =?UTF-8?q?=E2=9C=A8=20powWad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/BitwiseLib.sol | 24 ----------- src/utils/FixedPointMathLib.sol | 73 +++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 55 deletions(-) delete mode 100644 src/utils/BitwiseLib.sol diff --git a/src/utils/BitwiseLib.sol b/src/utils/BitwiseLib.sol deleted file mode 100644 index 7feb3e4c..00000000 --- a/src/utils/BitwiseLib.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -pragma solidity >=0.8.0; - -/// @notice Bitwise library with operations for bit strings and integers. -library BitwiseLib { - // Integer log2 - // Closely related to count-leading-zeros. - // See - // @returns floor(log2(x)) if x is nonzero, otherwise 0. - // This is the same as the location of the highest set bit. - // Consumes 232 gas. This could have been an 3 gas EVM opcode though. - function ilog2(uint256 x) internal returns (uint256 r) { - assembly { - r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) - r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) - r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) - r := or(r, shl(4, lt(0xffff, shr(r, x)))) - r := or(r, shl(3, lt(0xff, shr(r, x)))) - r := or(r, shl(2, lt(0xf, shr(r, x)))) - r := or(r, shl(1, lt(0x3, shr(r, x)))) - r := or(r, lt(0x1, shr(r, x))) - } - } -} diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index d18f928f..e29a40f4 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; -import {BitwiseLib} from "./BitwiseLib.sol"; - /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) library FixedPointMathLib { @@ -32,14 +30,19 @@ library FixedPointMathLib { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } + function powWad(int256 x, int256 y) internal pure returns (int256) { + // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y) + return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0. + } + function expWad(int256 x) internal pure returns (int256 r) { unchecked { // When the result is < 0.5 we return zero. This happens when // x <= floor(log(0.5e18) * 1e18) ~ -42e18 if (x <= -42139678854452767551) return 0; - // When the result is > (2**255 - 1) / 1e18 we can not represent it - // as an int256. This happens when x >= floor(log((2**255 -1) / 1e18) * 1e18) ~ 135. + // When the result is > (2**255 - 1) / 1e18 we can not represent it as an + // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135. if (x >= 135305999368893231589) revert("EXP_OVERFLOW"); // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 @@ -47,8 +50,8 @@ library FixedPointMathLib { // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. x = (x << 78) / 5**18; - // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers of two - // such that exp(x) = exp(x') * 2**k, where k is an integer. + // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers + // of two such that exp(x) = exp(x') * 2**k, where k is an integer. // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96; x = x - k * 54916777467707473351141471128; @@ -72,7 +75,7 @@ library FixedPointMathLib { q = ((q * x) >> 96) + 26449188498355588339934803723976023; assembly { - // Div in assembly because solidity adds a zero check despite the `unchecked`. + // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial won't have zeros in the domain as all its roots are complex. // No scaling is necessary because p is already 2**96 too large. r := sdiv(p, q) @@ -81,42 +84,32 @@ library FixedPointMathLib { // r should be in the range (0.09, 0.25) * 2**96. // We now need to multiply r by: - // - the scale factor s = ~6.031367120. - // - the 2**k factor from the range reduction. - // - the 1e18 / 2**96 factor for base conversion. + // * the scale factor s = ~6.031367120. + // * the 2**k factor from the range reduction. + // * the 1e18 / 2**96 factor for base conversion. // We do this all at once, with an intermediate result in 2**213 // basis, so the final right shift is always by a positive amount. r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)); } } - // Computes ln(x) in 1e18 fixed point. - // Reverts if x is negative or zero. - // @param x The number to compute ln(x) for. - // @returns Approximately ln(x / 1e18) * 1e18 if x is strictly positive, - // reverts with `LnNegativeUndefined()` if x is negative, and with - // `Overflow()` if x is zero. - // Consumes about 670 gas. - function lnWad(int256 x) internal returns (int256 r) { + function lnWad(int256 x) internal pure returns (int256 r) { unchecked { - if (x < 1) { - if (x < 0) revert LnNegativeUndefined(); - revert Overflow(); - } + require(x > 0, "UNDEFINED"); // We want to convert x from 10**18 fixed point to 2**96 fixed point. - // We do this by multiplying by 2**96 / 10**18. - // But since ln(x * C) = ln(x) + ln(C), we can simply do nothing here + // We do this by multiplying by 2**96 / 10**18. But since + // ln(x * C) = ln(x) + ln(C), we can simply do nothing here // and add ln(2**96 / 10**18) at the end. // Reduce range of x to (1, 2) * 2**96 // ln(2^k * x) = k * ln(2) + ln(x) - int256 k = int256(BitwiseLib.ilog2(uint256(x))) - 96; + int256 k = int256(log2(uint256(x))) - 96; x <<= uint256(159 - k); x = int256(uint256(x) >> 159); - // Evaluate using a (8, 8)-term rational approximation - // p is made monic, we will multiply by a scale factor later + // Evaluate using a (8, 8)-term rational approximation. + // p is made monic, we will multiply by a scale factor later. int256 p = x + 3273285459638523848632254066296; p = ((p * x) >> 96) + 24828157081833163892658089445524; p = ((p * x) >> 96) + 43456485725739037958740375743393; @@ -124,8 +117,9 @@ library FixedPointMathLib { p = ((p * x) >> 96) - 45023709667254063763336534515857; p = ((p * x) >> 96) - 14706773417378608786704636184526; p = p * x - (795164235651350426258249787498 << 96); + // We leave p in 2**192 basis so we don't need to scale it back up for the division. - // q is monic by convention + // q is monic by convention. int256 q = x + 5573035233440673466300451813936; q = ((q * x) >> 96) + 71694874799317883764090561454958; q = ((q * x) >> 96) + 283447036172924575727196451306956; @@ -134,18 +128,20 @@ library FixedPointMathLib { q = ((q * x) >> 96) + 31853899698501571402653359427138; q = ((q * x) >> 96) + 909429971244387300277376558375; assembly { - // Div in assembly because solidity adds a zero check despite the `unchecked`. - // The q polynomial is known not to have zeros in the domain. (All roots are complex) + // Div in assembly because solidity adds a zero check despite the unchecked. + // The q polynomial is known not to have zeros in the domain. // No scaling required because p is already 2**96 too large. r := sdiv(p, q) } + // r is in the range (0, 0.125) * 2**96 - // Finalization, we need to + // Finalization, we need to: // * multiply by the scale factor s = 5.549… // * add ln(2**96 / 10**18) // * add k * ln(2) // * multiply by 10**18 / 2**96 = 5**18 >> 78 + // mul s * 5e18 * 2**96, base is now 5**18 * 2**192 r *= 1677202110996718588342820967067443963516166; // add ln(2) * k * 5e18 * 2**192 @@ -358,4 +354,19 @@ library FixedPointMathLib { } } } + + function log2(uint256 x) internal pure returns (uint256 r) { + require(x > 0, "UNDEFINED"); + + assembly { + r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) + r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) + r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) + r := or(r, shl(4, lt(0xffff, shr(r, x)))) + r := or(r, shl(3, lt(0xff, shr(r, x)))) + r := or(r, shl(2, lt(0xf, shr(r, x)))) + r := or(r, shl(1, lt(0x3, shr(r, x)))) + r := or(r, lt(0x1, shr(r, x))) + } + } } From eff01a402df301fa61035be441d62ae0d059b3ac Mon Sep 17 00:00:00 2001 From: t11s Date: Tue, 17 May 2022 17:15:22 -0700 Subject: [PATCH 19/44] =?UTF-8?q?=E2=9C=85=20Log2=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 17 +++++++++-------- src/test/BitwiseLib.t.sol | 17 ----------------- src/test/FixedPointMathLib.t.sol | 16 ++++++++++++++++ src/utils/FixedPointMathLib.sol | 4 ---- 4 files changed, 25 insertions(+), 29 deletions(-) delete mode 100644 src/test/BitwiseLib.t.sol diff --git a/.gas-snapshot b/.gas-snapshot index 420d5b37..8129b5d4 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -13,7 +13,6 @@ AuthTest:testSetAuthorityAsOwnerWithOutOfOrderAuthority() (gas: 226463) AuthTest:testSetAuthorityWithPermissiveAuthority() (gas: 125918) AuthTest:testSetOwnerAsOwner() (gas: 15276) AuthTest:testSetOwnerWithPermissiveAuthority() (gas: 127906) -BitwiseLibTest:testIlog() (gas: 283929) Bytes32AddressLibTest:testFillLast12Bytes() (gas: 223) Bytes32AddressLibTest:testFromLast20Bytes() (gas: 191) CREATE3Test:testDeployERC20() (gas: 852410) @@ -165,25 +164,27 @@ ERC721Test:testTransferFromApproveAll() (gas: 92897) ERC721Test:testTransferFromSelf() (gas: 64820) FixedPointMathLibTest:testDivWadDown() (gas: 831) FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 435) -FixedPointMathLibTest:testDivWadUp() (gas: 971) +FixedPointMathLibTest:testDivWadUp() (gas: 927) FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 450) FixedPointMathLibTest:testExpWad() (gas: 7303) FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 330) -FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 331) +FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 353) FixedPointMathLibTest:testFailMulDivDownZeroDenominator() (gas: 294) FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 296) -FixedPointMathLibTest:testLnWad() (gas: 2278) -FixedPointMathLibTest:testLnWadBig() (gas: 2276) +FixedPointMathLibTest:testFuzzLog() (gas: 315733) +FixedPointMathLibTest:testLnWad() (gas: 2416) +FixedPointMathLibTest:testLnWadBig() (gas: 2414) FixedPointMathLibTest:testLnWadNegative() (gas: 232) FixedPointMathLibTest:testLnWadOverfloww() (gas: 232) -FixedPointMathLibTest:testLnWadSmall() (gas: 2936) +FixedPointMathLibTest:testLnWadSmall() (gas: 3120) +FixedPointMathLibTest:testLog2() (gas: 1755) FixedPointMathLibTest:testMulDivDown() (gas: 1883) FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 729) FixedPointMathLibTest:testMulDivUp() (gas: 2250) FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 846) FixedPointMathLibTest:testMulWadDown() (gas: 844) -FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 843) -FixedPointMathLibTest:testMulWadUp() (gas: 958) +FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 865) +FixedPointMathLibTest:testMulWadUp() (gas: 1003) FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 981) FixedPointMathLibTest:testRPow() (gas: 2142) FixedPointMathLibTest:testSqrt() (gas: 2156) diff --git a/src/test/BitwiseLib.t.sol b/src/test/BitwiseLib.t.sol deleted file mode 100644 index c759ef5e..00000000 --- a/src/test/BitwiseLib.t.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -pragma solidity 0.8.10; - -import {DSTestPlus} from "./utils/DSTestPlus.sol"; - -import {BitwiseLib} from "../utils/BitwiseLib.sol"; - -contract BitwiseLibTest is DSTestPlus { - function testIlog() public { - assertEq(BitwiseLib.ilog2(0), 0); - for (uint256 i = 1; i < 255; i++) { - assertEq(BitwiseLib.ilog2((1 << i) - 1), i - 1); - assertEq(BitwiseLib.ilog2((1 << i)), i); - assertEq(BitwiseLib.ilog2((1 << i) + 1), i); - } - } -} diff --git a/src/test/FixedPointMathLib.t.sol b/src/test/FixedPointMathLib.t.sol index 159cd32b..3fbfae68 100644 --- a/src/test/FixedPointMathLib.t.sol +++ b/src/test/FixedPointMathLib.t.sol @@ -223,6 +223,14 @@ contract FixedPointMathLibTest is DSTestPlus { assertEq(FixedPointMathLib.sqrt(32239684), 5678); } + function testLog2() public { + assertEq(FixedPointMathLib.log2(2), 1); + assertEq(FixedPointMathLib.log2(4), 2); + assertEq(FixedPointMathLib.log2(1024), 10); + assertEq(FixedPointMathLib.log2(1048576), 20); + assertEq(FixedPointMathLib.log2(1073741824), 30); + } + function testFuzzMulWadDown(uint256 x, uint256 y) public { // Ignore cases where x * y overflows. unchecked { @@ -374,4 +382,12 @@ contract FixedPointMathLibTest is DSTestPlus { assertTrue(root * root <= x && next * next > x); } + + function testFuzzLog2() public { + for (uint256 i = 1; i < 255; i++) { + assertEq(FixedPointMathLib.log2((1 << i) - 1), i - 1); + assertEq(FixedPointMathLib.log2((1 << i)), i); + assertEq(FixedPointMathLib.log2((1 << i) + 1), i); + } + } } diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index e29a40f4..9b9a1680 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -4,10 +4,6 @@ pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) library FixedPointMathLib { - error Overflow(); - - error LnNegativeUndefined(); - /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ From deb69bd0b4b8e8f99632077208ee15ef5349e40b Mon Sep 17 00:00:00 2001 From: t11s Date: Tue, 17 May 2022 17:36:36 -0700 Subject: [PATCH 20/44] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Name=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 16 ++++++++-------- src/test/FixedPointMathLib.t.sol | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 8129b5d4..619d23eb 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -164,26 +164,26 @@ ERC721Test:testTransferFromApproveAll() (gas: 92897) ERC721Test:testTransferFromSelf() (gas: 64820) FixedPointMathLibTest:testDivWadDown() (gas: 831) FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 435) -FixedPointMathLibTest:testDivWadUp() (gas: 927) +FixedPointMathLibTest:testDivWadUp() (gas: 949) FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 450) FixedPointMathLibTest:testExpWad() (gas: 7303) FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 330) -FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 353) -FixedPointMathLibTest:testFailMulDivDownZeroDenominator() (gas: 294) +FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 309) +FixedPointMathLibTest:testFailMulDivDownZeroDenominator() (gas: 338) FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 296) -FixedPointMathLibTest:testFuzzLog() (gas: 315733) +FixedPointMathLibTest:testFuzzLog2() (gas: 315757) FixedPointMathLibTest:testLnWad() (gas: 2416) -FixedPointMathLibTest:testLnWadBig() (gas: 2414) +FixedPointMathLibTest:testLnWadBig() (gas: 2392) FixedPointMathLibTest:testLnWadNegative() (gas: 232) -FixedPointMathLibTest:testLnWadOverfloww() (gas: 232) -FixedPointMathLibTest:testLnWadSmall() (gas: 3120) +FixedPointMathLibTest:testLnWadOverflow() (gas: 209) +FixedPointMathLibTest:testLnWadSmall() (gas: 3142) FixedPointMathLibTest:testLog2() (gas: 1755) FixedPointMathLibTest:testMulDivDown() (gas: 1883) FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 729) FixedPointMathLibTest:testMulDivUp() (gas: 2250) FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 846) FixedPointMathLibTest:testMulWadDown() (gas: 844) -FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 865) +FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 887) FixedPointMathLibTest:testMulWadUp() (gas: 1003) FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 981) FixedPointMathLibTest:testRPow() (gas: 2142) diff --git a/src/test/FixedPointMathLib.t.sol b/src/test/FixedPointMathLib.t.sol index 3fbfae68..3cca0ed8 100644 --- a/src/test/FixedPointMathLib.t.sol +++ b/src/test/FixedPointMathLib.t.sol @@ -202,7 +202,7 @@ contract FixedPointMathLibTest is DSTestPlus { // FixedPointMathLib.lnWad(-2**255); } - function testLnWadOverfloww() public { + function testLnWadOverflow() public { // TODO: Blocked on // hevm.expectRevert(FixedPointMathLib.Overflow.selector); // FixedPointMathLib.lnWad(0); From f878f20ecd6a23dd4105ee3eed7291b6311ce1fb Mon Sep 17 00:00:00 2001 From: Vectorized Date: Wed, 18 May 2022 22:52:42 +0800 Subject: [PATCH 21/44] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20MerkleProof=20Verify?= =?UTF-8?q?=20Optimization=20(#240)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 10 +++++----- src/utils/MerkleProof.sol | 27 ++++++++++++--------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 619d23eb..e473fbad 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -101,7 +101,7 @@ ERC20Test:testApprove() (gas: 31080) ERC20Test:testBurn() (gas: 57014) ERC20Test:testFailPermitBadDeadline() (gas: 36924) ERC20Test:testFailPermitBadNonce() (gas: 36874) -ERC20Test:testFailPermitPastDeadline() (gas: 10938) +ERC20Test:testFailPermitPastDeadline() (gas: 8589) ERC20Test:testFailPermitReplay() (gas: 66285) ERC20Test:testFailTransferFromInsufficientAllowance() (gas: 80837) ERC20Test:testFailTransferFromInsufficientBalance() (gas: 81336) @@ -188,10 +188,10 @@ FixedPointMathLibTest:testMulWadUp() (gas: 1003) FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 981) FixedPointMathLibTest:testRPow() (gas: 2142) FixedPointMathLibTest:testSqrt() (gas: 2156) -MerkleProofTest:testValidProofSupplied() (gas: 991) -MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 392) -MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 389) -MerkleProofTest:testVerifyInvalidProofSupplied() (gas: 977) +MerkleProofTest:testValidProofSupplied() (gas: 945) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 390) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 387) +MerkleProofTest:testVerifyInvalidProofSupplied() (gas: 931) MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34293) MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80575) MultiRolesAuthorityTest:testCanCallWithCustomAuthority() (gas: 422681) diff --git a/src/utils/MerkleProof.sol b/src/utils/MerkleProof.sol index 86eeebe5..a5df76ed 100644 --- a/src/utils/MerkleProof.sol +++ b/src/utils/MerkleProof.sol @@ -18,26 +18,23 @@ library MerkleProof { // Iterate over proof elements to compute root hash. for { - let end := add(data, mul(mload(proof), 0x20)) + // Left shift by 5 is equivalent to multiplying by 0x20. + let end := add(data, shl(5, mload(proof))) } lt(data, end) { data := add(data, 0x20) } { let loadedData := mload(data) - switch gt(computedHash, loadedData) - case 0 { - // Store elements to hash contiguously in scratch space. - // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. - mstore(0x00, computedHash) - mstore(0x20, loadedData) - computedHash := keccak256(0x00, 0x40) - } - default { - mstore(0x00, loadedData) - mstore(0x20, computedHash) - computedHash := keccak256(0x00, 0x40) - } + // Slot of `computedHash` in scratch space. + // If the condition is true: 0x20, otherwise: 0x00. + let scratch := shl(5, gt(computedHash, loadedData)) + + // Store elements to hash contiguously in scratch space. + // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. + mstore(scratch, computedHash) + mstore(xor(scratch, 0x20), loadedData) + computedHash := keccak256(0x00, 0x40) } isValid := eq(computedHash, root) } } -} +} \ No newline at end of file From 34e2edfa459db66b1062b53ebef13ac0af0782e5 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Thu, 19 May 2022 11:26:20 +0800 Subject: [PATCH 22/44] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20MerkleProof:=20memor?= =?UTF-8?q?y=20->=20calldata=20(#243)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add calldata verify * Snapshot * Fix snapshot * Remove memory version of verify --- .gas-snapshot | 10 +++++----- src/test/MerkleProof.t.sol | 18 ++++++++++++------ src/utils/MerkleProof.sol | 14 +++++++------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index e473fbad..d61fb9d3 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -101,7 +101,7 @@ ERC20Test:testApprove() (gas: 31080) ERC20Test:testBurn() (gas: 57014) ERC20Test:testFailPermitBadDeadline() (gas: 36924) ERC20Test:testFailPermitBadNonce() (gas: 36874) -ERC20Test:testFailPermitPastDeadline() (gas: 8589) +ERC20Test:testFailPermitPastDeadline() (gas: 10938) ERC20Test:testFailPermitReplay() (gas: 66285) ERC20Test:testFailTransferFromInsufficientAllowance() (gas: 80837) ERC20Test:testFailTransferFromInsufficientBalance() (gas: 81336) @@ -188,10 +188,10 @@ FixedPointMathLibTest:testMulWadUp() (gas: 1003) FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 981) FixedPointMathLibTest:testRPow() (gas: 2142) FixedPointMathLibTest:testSqrt() (gas: 2156) -MerkleProofTest:testValidProofSupplied() (gas: 945) -MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 390) -MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 387) -MerkleProofTest:testVerifyInvalidProofSupplied() (gas: 931) +MerkleProofTest:testValidProofSupplied() (gas: 2217) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 1498) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 1492) +MerkleProofTest:testVerifyInvalidProofSupplied() (gas: 2236) MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34293) MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80575) MultiRolesAuthorityTest:testCanCallWithCustomAuthority() (gas: 422681) diff --git a/src/test/MerkleProof.t.sol b/src/test/MerkleProof.t.sol index cbfb562c..c136c12b 100644 --- a/src/test/MerkleProof.t.sol +++ b/src/test/MerkleProof.t.sol @@ -8,13 +8,13 @@ import {MerkleProof} from "../utils/MerkleProof.sol"; contract MerkleProofTest is DSTestPlus { function testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() public { bytes32[] memory proof; - assertBoolEq(MerkleProof.verify(proof, 0x00, 0x00), true); + assertBoolEq(this.verify(proof, 0x00, 0x00), true); } function testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() public { bytes32[] memory proof; bytes32 leaf = "a"; - assertBoolEq(MerkleProof.verify(proof, 0x00, leaf), false); + assertBoolEq(this.verify(proof, 0x00, leaf), false); } function testValidProofSupplied() public { @@ -24,8 +24,8 @@ contract MerkleProofTest is DSTestPlus { proof[0] = 0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510; proof[1] = 0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2; bytes32 root = 0x5842148bc6ebeb52af882a317c765fccd3ae80589b21a9b8cbf21abb630e46a7; - bytes32 leaf = 0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb; - assertBoolEq(MerkleProof.verify(proof, root, leaf), true); + bytes32 leaf = 0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb; + assertBoolEq(this.verify(proof, root, leaf), true); } function testVerifyInvalidProofSupplied() public { @@ -37,8 +37,14 @@ contract MerkleProofTest is DSTestPlus { proof[1] = 0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2; bytes32 root = 0x5842148bc6ebeb52af882a317c765fccd3ae80589b21a9b8cbf21abb630e46a7; bytes32 leaf = 0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb; - assertBoolEq(MerkleProof.verify(proof, root, leaf), false); + assertBoolEq(this.verify(proof, root, leaf), false); } - + function verify( + bytes32[] calldata proof, + bytes32 root, + bytes32 leaf + ) external pure returns (bool) { + return MerkleProof.verify(proof, root, leaf); + } } diff --git a/src/utils/MerkleProof.sol b/src/utils/MerkleProof.sol index a5df76ed..f58fe4d7 100644 --- a/src/utils/MerkleProof.sol +++ b/src/utils/MerkleProof.sol @@ -6,28 +6,28 @@ pragma solidity >=0.8.0; /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) library MerkleProof { function verify( - bytes32[] memory proof, + bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool isValid) { assembly { let computedHash := leaf - // Get the memory start location of the first element in the proof array. - let data := add(proof, 0x20) + // Initialize `data` to the offset of `proof` in the calldata. + let data := proof.offset // Iterate over proof elements to compute root hash. for { // Left shift by 5 is equivalent to multiplying by 0x20. - let end := add(data, shl(5, mload(proof))) + let end := add(data, shl(5, proof.length)) } lt(data, end) { data := add(data, 0x20) } { - let loadedData := mload(data) + let loadedData := calldataload(data) // Slot of `computedHash` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(computedHash, loadedData)) - + // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, computedHash) @@ -37,4 +37,4 @@ library MerkleProof { isValid := eq(computedHash, root) } } -} \ No newline at end of file +} From 264054c8409081571464e3307a22c3299c23ee28 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Tue, 24 May 2022 02:09:45 +0800 Subject: [PATCH 23/44] =?UTF-8?q?=E2=9C=A8=20LibBitmap=20tests=20and=20tin?= =?UTF-8?q?y=20optimization=20(#249)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 3 ++ src/test/LibBitmap.t.sol | 41 ++++++++++++++++++++++++++ src/test/utils/mocks/MockLibBitmap.sol | 25 ++++++++++++++++ src/utils/LibBitmap.sol | 16 +++++++++- 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/test/LibBitmap.t.sol create mode 100644 src/test/utils/mocks/MockLibBitmap.sol diff --git a/.gas-snapshot b/.gas-snapshot index d61fb9d3..13e8a6cd 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -188,6 +188,9 @@ FixedPointMathLibTest:testMulWadUp() (gas: 1003) FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 981) FixedPointMathLibTest:testRPow() (gas: 2142) FixedPointMathLibTest:testSqrt() (gas: 2156) +LibBitmapTest:testBitmapGet() (gas: 7806) +LibBitmapTest:testBitmapSet() (gas: 28649) +LibBitmapTest:testBitmapSetTo() (gas: 20672) MerkleProofTest:testValidProofSupplied() (gas: 2217) MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 1498) MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 1492) diff --git a/src/test/LibBitmap.t.sol b/src/test/LibBitmap.t.sol new file mode 100644 index 00000000..a9bfd778 --- /dev/null +++ b/src/test/LibBitmap.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity 0.8.10; + +import {DSTestPlus} from "./utils/DSTestPlus.sol"; + +import {MockLibBitmap} from "./utils/mocks/MockLibBitmap.sol"; + +contract LibBitmapTest is DSTestPlus { + MockLibBitmap mockLibBitmap; + + function setUp() public { + mockLibBitmap = new MockLibBitmap(); + } + + function testBitmapGet() public { + testBitmapGet(123); + } + + function testBitmapGet(uint256 index) public { + assertFalse(mockLibBitmap.get(index)); + } + + function testBitmapSet() public { + testBitmapSet(123); + } + + function testBitmapSet(uint256 index) public { + mockLibBitmap.set(index); + assertTrue(mockLibBitmap.get(index)); + } + + function testBitmapSetTo() public { + testBitmapSetTo(123, true); + testBitmapSetTo(123, false); + } + + function testBitmapSetTo(uint256 index, bool shouldSet) public { + mockLibBitmap.setTo(index, shouldSet); + assertTrue(mockLibBitmap.get(index) == shouldSet); + } +} diff --git a/src/test/utils/mocks/MockLibBitmap.sol b/src/test/utils/mocks/MockLibBitmap.sol new file mode 100644 index 00000000..9d702a64 --- /dev/null +++ b/src/test/utils/mocks/MockLibBitmap.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.0; + +import {LibBitmap} from "../../../utils/LibBitmap.sol"; + +contract MockLibBitmap { + using LibBitmap for LibBitmap.Bitmap; + LibBitmap.Bitmap bitmap; + + function get(uint256 index) public view returns (bool result) { + result = bitmap.get(index); + } + + function set(uint256 index) public { + bitmap.set(index); + } + + function unset(uint256 index) public { + bitmap.unset(index); + } + + function setTo(uint256 index, bool shouldSet) public { + bitmap.setTo(index, shouldSet); + } +} diff --git a/src/utils/LibBitmap.sol b/src/utils/LibBitmap.sol index a489037e..f6bd8260 100644 --- a/src/utils/LibBitmap.sol +++ b/src/utils/LibBitmap.sol @@ -29,6 +29,20 @@ library LibBitmap { uint256 index, bool shouldSet ) internal { - shouldSet ? set(bitmap, index) : unset(bitmap, index); + uint256 value = bitmap.map[index >> 8]; + + assembly { + // The following sets the bit at `shift` without branching. + let shift := and(index, 0xff) + // Isolate the bit at `shift`. + let x := and(shr(shift, value), 1) + // Xor it with `shouldSet`. Results in 1 if both are different, else 0. + x := xor(x, shouldSet) + // Shifts the bit back. Then, xor with value. + // Only the bit at `shift` will be flipped if they differ. + // Every other bit will stay the same, as they are xor'ed with zeroes. + value := xor(value, shl(shift, x)) + } + bitmap.map[index >> 8] = value; } } From ccfba5e69dd863eaa3d5d0efee12fdc6ce70aacc Mon Sep 17 00:00:00 2001 From: t11s Date: Tue, 24 May 2022 09:05:20 -0700 Subject: [PATCH 24/44] 7.0.0-alpha.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index fdffe65e..67dc21b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@rari-capital/solmate", - "version": "6.2.0", + "version": "7.0.0-alpha.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 451a2e56..4b95fdec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@rari-capital/solmate", "license": "AGPL-3.0-only", - "version": "6.2.0", + "version": "7.0.0-alpha.0", "description": "Modern, opinionated and gas optimized building blocks for smart contract development.", "files": [ "src/**/*.sol" From 1e977ca7c1b179b5f13e9cd0ab42d35c0e5ff746 Mon Sep 17 00:00:00 2001 From: t11s Date: Tue, 24 May 2022 09:08:44 -0700 Subject: [PATCH 25/44] 7.0.0-alpha.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 67dc21b0..a9f50dbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@rari-capital/solmate", - "version": "7.0.0-alpha.0", + "version": "7.0.0-alpha.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4b95fdec..eb440798 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@rari-capital/solmate", "license": "AGPL-3.0-only", - "version": "7.0.0-alpha.0", + "version": "7.0.0-alpha.1", "description": "Modern, opinionated and gas optimized building blocks for smart contract development.", "files": [ "src/**/*.sol" From 945dd66b0d49379478f436f3f91e2177c2834436 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Sat, 28 May 2022 02:48:46 +0800 Subject: [PATCH 26/44] =?UTF-8?q?=E2=9A=A1=20Tiny=20branchless=20sqrt=20op?= =?UTF-8?q?timization=20(#258)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Branchless last block * Edit comment --- .gas-snapshot | 2 +- src/utils/FixedPointMathLib.sol | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 13e8a6cd..493d470a 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -187,7 +187,7 @@ FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 887) FixedPointMathLibTest:testMulWadUp() (gas: 1003) FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 981) FixedPointMathLibTest:testRPow() (gas: 2142) -FixedPointMathLibTest:testSqrt() (gas: 2156) +FixedPointMathLibTest:testSqrt() (gas: 2091) LibBitmapTest:testBitmapGet() (gas: 7806) LibBitmapTest:testBitmapSet() (gas: 28649) LibBitmapTest:testBitmapSetTo() (gas: 20672) diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index 9b9a1680..b23c0ecc 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -341,13 +341,11 @@ library FixedPointMathLib { z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between - // floor(sqrt(x)) and ceil(sqrt(x)). This check ensures we return floor. + // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. - // If you don't care whether the floor or ceil square root is returned, you can remove this block. - if lt(div(x, z), z) { - z := div(x, z) - } + // If you don't care whether the floor or ceil square root is returned, you can remove this statement. + z := sub(z, lt(div(x, z), z)) } } From 983e1d65dfb5880c57ff9106c5ed47270a4d6961 Mon Sep 17 00:00:00 2001 From: t11s Date: Fri, 27 May 2022 12:08:24 -0700 Subject: [PATCH 27/44] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20AGPL=20->=20MIT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/auth/Auth.sol | 2 +- src/auth/authorities/MultiRolesAuthority.sol | 2 +- src/auth/authorities/RolesAuthority.sol | 2 +- src/mixins/ERC4626.sol | 2 +- src/test/Auth.t.sol | 2 +- src/test/Bytes32AddressLib.t.sol | 2 +- src/test/CREATE3.t.sol | 2 +- src/test/DSTestPlus.t.sol | 2 +- src/test/ERC1155.t.sol | 2 +- src/test/ERC1155B.t.sol | 2 +- src/test/ERC20.t.sol | 2 +- src/test/ERC4626.t.sol | 2 +- src/test/ERC721.t.sol | 2 +- src/test/FixedPointMathLib.t.sol | 2 +- src/test/LibBitmap.t.sol | 2 +- src/test/MerkleProof.t.sol | 2 +- src/test/MultiRolesAuthority.t.sol | 2 +- src/test/ReentrancyGuard.t.sol | 2 +- src/test/RolesAuthority.t.sol | 2 +- src/test/SSTORE2.t.sol | 2 +- src/test/SafeCastLib.t.sol | 2 +- src/test/SafeTransferLib.t.sol | 2 +- src/test/WETH.t.sol | 2 +- src/test/utils/DSInvariantTest.sol | 2 +- src/test/utils/DSTestPlus.sol | 2 +- src/test/utils/Hevm.sol | 2 +- src/test/utils/mocks/MockAuthChild.sol | 2 +- src/test/utils/mocks/MockAuthority.sol | 2 +- src/test/utils/mocks/MockERC1155.sol | 2 +- src/test/utils/mocks/MockERC1155B.sol | 2 +- src/test/utils/mocks/MockERC20.sol | 2 +- src/test/utils/mocks/MockERC4626.sol | 2 +- src/test/utils/mocks/MockERC721.sol | 2 +- src/test/utils/mocks/MockLibBitmap.sol | 2 +- src/test/utils/users/ERC1155BUser.sol | 2 +- src/test/utils/weird-tokens/MissingReturnToken.sol | 2 +- src/test/utils/weird-tokens/ReturnsFalseToken.sol | 2 +- src/test/utils/weird-tokens/ReturnsGarbageToken.sol | 2 +- src/test/utils/weird-tokens/ReturnsTooLittleToken.sol | 2 +- src/test/utils/weird-tokens/ReturnsTooMuchToken.sol | 2 +- src/test/utils/weird-tokens/ReturnsTwoToken.sol | 2 +- src/test/utils/weird-tokens/RevertingToken.sol | 2 +- src/tokens/ERC1155.sol | 2 +- src/tokens/ERC1155B.sol | 2 +- src/tokens/ERC20.sol | 2 +- src/tokens/ERC721.sol | 2 +- src/tokens/WETH.sol | 2 +- src/utils/Bytes32AddressLib.sol | 2 +- src/utils/CREATE3.sol | 2 +- src/utils/FixedPointMathLib.sol | 2 +- src/utils/LibBitmap.sol | 2 +- src/utils/LibRLP.sol | 2 +- src/utils/LibString.sol | 2 +- src/utils/MerkleProof.sol | 2 +- src/utils/ReentrancyGuard.sol | 2 +- src/utils/SSTORE2.sol | 2 +- src/utils/SafeCastLib.sol | 2 +- src/utils/SafeTransferLib.sol | 2 +- 59 files changed, 59 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index eb440798..b481b414 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rari-capital/solmate", - "license": "AGPL-3.0-only", + "license": "MIT", "version": "7.0.0-alpha.1", "description": "Modern, opinionated and gas optimized building blocks for smart contract development.", "files": [ diff --git a/src/auth/Auth.sol b/src/auth/Auth.sol index 48edaa42..ef3a9d06 100644 --- a/src/auth/Auth.sol +++ b/src/auth/Auth.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic. diff --git a/src/auth/authorities/MultiRolesAuthority.sol b/src/auth/authorities/MultiRolesAuthority.sol index 8ecd3cdd..6ae1a460 100644 --- a/src/auth/authorities/MultiRolesAuthority.sol +++ b/src/auth/authorities/MultiRolesAuthority.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {Auth, Authority} from "../Auth.sol"; diff --git a/src/auth/authorities/RolesAuthority.sol b/src/auth/authorities/RolesAuthority.sol index afefe1ad..e42a2637 100644 --- a/src/auth/authorities/RolesAuthority.sol +++ b/src/auth/authorities/RolesAuthority.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {Auth, Authority} from "../Auth.sol"; diff --git a/src/mixins/ERC4626.sol b/src/mixins/ERC4626.sol index 704e0d44..35488b28 100644 --- a/src/mixins/ERC4626.sol +++ b/src/mixins/ERC4626.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; diff --git a/src/test/Auth.t.sol b/src/test/Auth.t.sol index 5cb58d74..00e29ccf 100644 --- a/src/test/Auth.t.sol +++ b/src/test/Auth.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/Bytes32AddressLib.t.sol b/src/test/Bytes32AddressLib.t.sol index 0a85b141..50d8f971 100644 --- a/src/test/Bytes32AddressLib.t.sol +++ b/src/test/Bytes32AddressLib.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/CREATE3.t.sol b/src/test/CREATE3.t.sol index b09ee045..64e25751 100644 --- a/src/test/CREATE3.t.sol +++ b/src/test/CREATE3.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {WETH} from "../tokens/WETH.sol"; diff --git a/src/test/DSTestPlus.t.sol b/src/test/DSTestPlus.t.sol index c6bf8894..4842abf8 100644 --- a/src/test/DSTestPlus.t.sol +++ b/src/test/DSTestPlus.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/ERC1155.t.sol b/src/test/ERC1155.t.sol index 550146e1..dd76a494 100644 --- a/src/test/ERC1155.t.sol +++ b/src/test/ERC1155.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/ERC1155B.t.sol b/src/test/ERC1155B.t.sol index 403837c8..014e4094 100644 --- a/src/test/ERC1155B.t.sol +++ b/src/test/ERC1155B.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/ERC20.t.sol b/src/test/ERC20.t.sol index 2d61c78c..530a8b2d 100644 --- a/src/test/ERC20.t.sol +++ b/src/test/ERC20.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/ERC4626.t.sol b/src/test/ERC4626.t.sol index 66aa8066..3c143a96 100644 --- a/src/test/ERC4626.t.sol +++ b/src/test/ERC4626.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/ERC721.t.sol b/src/test/ERC721.t.sol index 45f8b9f4..d0d87a66 100644 --- a/src/test/ERC721.t.sol +++ b/src/test/ERC721.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/FixedPointMathLib.t.sol b/src/test/FixedPointMathLib.t.sol index 3cca0ed8..d8e71765 100644 --- a/src/test/FixedPointMathLib.t.sol +++ b/src/test/FixedPointMathLib.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/LibBitmap.t.sol b/src/test/LibBitmap.t.sol index a9bfd778..7ef65230 100644 --- a/src/test/LibBitmap.t.sol +++ b/src/test/LibBitmap.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/MerkleProof.t.sol b/src/test/MerkleProof.t.sol index c136c12b..e3e24bbc 100644 --- a/src/test/MerkleProof.t.sol +++ b/src/test/MerkleProof.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/MultiRolesAuthority.t.sol b/src/test/MultiRolesAuthority.t.sol index 98261fd5..65031923 100644 --- a/src/test/MultiRolesAuthority.t.sol +++ b/src/test/MultiRolesAuthority.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/ReentrancyGuard.t.sol b/src/test/ReentrancyGuard.t.sol index eb8a36cc..5bd3dbde 100644 --- a/src/test/ReentrancyGuard.t.sol +++ b/src/test/ReentrancyGuard.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/RolesAuthority.t.sol b/src/test/RolesAuthority.t.sol index 4249727c..6c36cb3e 100644 --- a/src/test/RolesAuthority.t.sol +++ b/src/test/RolesAuthority.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/SSTORE2.t.sol b/src/test/SSTORE2.t.sol index ac4232b0..c9f9fd0b 100644 --- a/src/test/SSTORE2.t.sol +++ b/src/test/SSTORE2.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/SafeCastLib.t.sol b/src/test/SafeCastLib.t.sol index 1631fbe3..b97b244b 100644 --- a/src/test/SafeCastLib.t.sol +++ b/src/test/SafeCastLib.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/SafeTransferLib.t.sol b/src/test/SafeTransferLib.t.sol index 2cbcd3c2..8bed492e 100644 --- a/src/test/SafeTransferLib.t.sol +++ b/src/test/SafeTransferLib.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {MockERC20} from "./utils/mocks/MockERC20.sol"; diff --git a/src/test/WETH.t.sol b/src/test/WETH.t.sol index 807a8fbf..8bcb86b0 100644 --- a/src/test/WETH.t.sol +++ b/src/test/WETH.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/utils/DSInvariantTest.sol b/src/test/utils/DSInvariantTest.sol index 820775c5..531a9fd4 100644 --- a/src/test/utils/DSInvariantTest.sol +++ b/src/test/utils/DSInvariantTest.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; contract DSInvariantTest { diff --git a/src/test/utils/DSTestPlus.sol b/src/test/utils/DSTestPlus.sol index 93c18c12..2ad69531 100644 --- a/src/test/utils/DSTestPlus.sol +++ b/src/test/utils/DSTestPlus.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {DSTest} from "ds-test/test.sol"; diff --git a/src/test/utils/Hevm.sol b/src/test/utils/Hevm.sol index 8ca0eff9..20f5a40a 100644 --- a/src/test/utils/Hevm.sol +++ b/src/test/utils/Hevm.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface Hevm { diff --git a/src/test/utils/mocks/MockAuthChild.sol b/src/test/utils/mocks/MockAuthChild.sol index d2c32760..df0deb5d 100644 --- a/src/test/utils/mocks/MockAuthChild.sol +++ b/src/test/utils/mocks/MockAuthChild.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {Auth, Authority} from "../../../auth/Auth.sol"; diff --git a/src/test/utils/mocks/MockAuthority.sol b/src/test/utils/mocks/MockAuthority.sol index acb36892..c8251db5 100644 --- a/src/test/utils/mocks/MockAuthority.sol +++ b/src/test/utils/mocks/MockAuthority.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {Authority} from "../../../auth/Auth.sol"; diff --git a/src/test/utils/mocks/MockERC1155.sol b/src/test/utils/mocks/MockERC1155.sol index ede086db..a3228ef8 100644 --- a/src/test/utils/mocks/MockERC1155.sol +++ b/src/test/utils/mocks/MockERC1155.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC1155} from "../../../tokens/ERC1155.sol"; diff --git a/src/test/utils/mocks/MockERC1155B.sol b/src/test/utils/mocks/MockERC1155B.sol index f263f3f5..29a97dbf 100644 --- a/src/test/utils/mocks/MockERC1155B.sol +++ b/src/test/utils/mocks/MockERC1155B.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC1155B} from "../../../tokens/ERC1155B.sol"; diff --git a/src/test/utils/mocks/MockERC20.sol b/src/test/utils/mocks/MockERC20.sol index fbbaef5a..35fc6486 100644 --- a/src/test/utils/mocks/MockERC20.sol +++ b/src/test/utils/mocks/MockERC20.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC20} from "../../../tokens/ERC20.sol"; diff --git a/src/test/utils/mocks/MockERC4626.sol b/src/test/utils/mocks/MockERC4626.sol index edc7d5f3..bfa9790f 100644 --- a/src/test/utils/mocks/MockERC4626.sol +++ b/src/test/utils/mocks/MockERC4626.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC20} from "../../../tokens/ERC20.sol"; diff --git a/src/test/utils/mocks/MockERC721.sol b/src/test/utils/mocks/MockERC721.sol index 51227c0e..7833a472 100644 --- a/src/test/utils/mocks/MockERC721.sol +++ b/src/test/utils/mocks/MockERC721.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC721} from "../../../tokens/ERC721.sol"; diff --git a/src/test/utils/mocks/MockLibBitmap.sol b/src/test/utils/mocks/MockLibBitmap.sol index 9d702a64..d981e62f 100644 --- a/src/test/utils/mocks/MockLibBitmap.sol +++ b/src/test/utils/mocks/MockLibBitmap.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {LibBitmap} from "../../../utils/LibBitmap.sol"; diff --git a/src/test/utils/users/ERC1155BUser.sol b/src/test/utils/users/ERC1155BUser.sol index 68c680ce..5ddcd767 100644 --- a/src/test/utils/users/ERC1155BUser.sol +++ b/src/test/utils/users/ERC1155BUser.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC1155TokenReceiver} from "../../../tokens/ERC1155.sol"; diff --git a/src/test/utils/weird-tokens/MissingReturnToken.sol b/src/test/utils/weird-tokens/MissingReturnToken.sol index 23f46336..e2959124 100644 --- a/src/test/utils/weird-tokens/MissingReturnToken.sol +++ b/src/test/utils/weird-tokens/MissingReturnToken.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; contract MissingReturnToken { diff --git a/src/test/utils/weird-tokens/ReturnsFalseToken.sol b/src/test/utils/weird-tokens/ReturnsFalseToken.sol index 8139efe7..2e41fb20 100644 --- a/src/test/utils/weird-tokens/ReturnsFalseToken.sol +++ b/src/test/utils/weird-tokens/ReturnsFalseToken.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; contract ReturnsFalseToken { diff --git a/src/test/utils/weird-tokens/ReturnsGarbageToken.sol b/src/test/utils/weird-tokens/ReturnsGarbageToken.sol index 77c95751..5fbfa75e 100644 --- a/src/test/utils/weird-tokens/ReturnsGarbageToken.sol +++ b/src/test/utils/weird-tokens/ReturnsGarbageToken.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; contract ReturnsGarbageToken { diff --git a/src/test/utils/weird-tokens/ReturnsTooLittleToken.sol b/src/test/utils/weird-tokens/ReturnsTooLittleToken.sol index 69947c30..0bf7a7b3 100644 --- a/src/test/utils/weird-tokens/ReturnsTooLittleToken.sol +++ b/src/test/utils/weird-tokens/ReturnsTooLittleToken.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; contract ReturnsTooLittleToken { diff --git a/src/test/utils/weird-tokens/ReturnsTooMuchToken.sol b/src/test/utils/weird-tokens/ReturnsTooMuchToken.sol index 8774cbbd..6b21c2a4 100644 --- a/src/test/utils/weird-tokens/ReturnsTooMuchToken.sol +++ b/src/test/utils/weird-tokens/ReturnsTooMuchToken.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; contract ReturnsTooMuchToken { diff --git a/src/test/utils/weird-tokens/ReturnsTwoToken.sol b/src/test/utils/weird-tokens/ReturnsTwoToken.sol index ac980f88..9af6eee7 100644 --- a/src/test/utils/weird-tokens/ReturnsTwoToken.sol +++ b/src/test/utils/weird-tokens/ReturnsTwoToken.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; contract ReturnsTwoToken { diff --git a/src/test/utils/weird-tokens/RevertingToken.sol b/src/test/utils/weird-tokens/RevertingToken.sol index 48ac1fa1..6ebac86f 100644 --- a/src/test/utils/weird-tokens/RevertingToken.sol +++ b/src/test/utils/weird-tokens/RevertingToken.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; contract RevertingToken { diff --git a/src/tokens/ERC1155.sol b/src/tokens/ERC1155.sol index df0aa1ae..603cac69 100644 --- a/src/tokens/ERC1155.sol +++ b/src/tokens/ERC1155.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. diff --git a/src/tokens/ERC1155B.sol b/src/tokens/ERC1155B.sol index ddb3a44f..c56e4479 100644 --- a/src/tokens/ERC1155B.sol +++ b/src/tokens/ERC1155B.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC1155TokenReceiver} from "./ERC1155.sol"; diff --git a/src/tokens/ERC20.sol b/src/tokens/ERC20.sol index 110314b5..d6f5194e 100644 --- a/src/tokens/ERC20.sol +++ b/src/tokens/ERC20.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. diff --git a/src/tokens/ERC721.sol b/src/tokens/ERC721.sol index f93d993a..15bdb043 100644 --- a/src/tokens/ERC721.sol +++ b/src/tokens/ERC721.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. diff --git a/src/tokens/WETH.sol b/src/tokens/WETH.sol index 5c470e37..8d57287c 100644 --- a/src/tokens/WETH.sol +++ b/src/tokens/WETH.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC20} from "./ERC20.sol"; diff --git a/src/utils/Bytes32AddressLib.sol b/src/utils/Bytes32AddressLib.sol index bc857be1..dea8e968 100644 --- a/src/utils/Bytes32AddressLib.sol +++ b/src/utils/Bytes32AddressLib.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Library for converting between addresses and bytes32 values. diff --git a/src/utils/CREATE3.sol b/src/utils/CREATE3.sol index 04e09155..d0c4e4c7 100644 --- a/src/utils/CREATE3.sol +++ b/src/utils/CREATE3.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {Bytes32AddressLib} from "./Bytes32AddressLib.sol"; diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index b23c0ecc..b09d81bb 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. diff --git a/src/utils/LibBitmap.sol b/src/utils/LibBitmap.sol index f6bd8260..0895319c 100644 --- a/src/utils/LibBitmap.sol +++ b/src/utils/LibBitmap.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Efficient bitmap library for mapping integers to single bit booleans. diff --git a/src/utils/LibRLP.sol b/src/utils/LibRLP.sol index 3fd9080c..6435f15e 100644 --- a/src/utils/LibRLP.sol +++ b/src/utils/LibRLP.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {Bytes32AddressLib} from "./Bytes32AddressLib.sol"; diff --git a/src/utils/LibString.sol b/src/utils/LibString.sol index 6cb8aa2d..04c07818 100644 --- a/src/utils/LibString.sol +++ b/src/utils/LibString.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Efficient library for creating string representations of integers. diff --git a/src/utils/MerkleProof.sol b/src/utils/MerkleProof.sol index f58fe4d7..f79f360f 100644 --- a/src/utils/MerkleProof.sol +++ b/src/utils/MerkleProof.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. diff --git a/src/utils/ReentrancyGuard.sol b/src/utils/ReentrancyGuard.sol index 9686ca22..9d8bd70d 100644 --- a/src/utils/ReentrancyGuard.sol +++ b/src/utils/ReentrancyGuard.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Gas optimized reentrancy protection for smart contracts. diff --git a/src/utils/SSTORE2.sol b/src/utils/SSTORE2.sol index bc10d72f..462bc86a 100644 --- a/src/utils/SSTORE2.sol +++ b/src/utils/SSTORE2.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Read and write to persistent storage at a fraction of the cost. diff --git a/src/utils/SafeCastLib.sol b/src/utils/SafeCastLib.sol index ab4287f7..030ed020 100644 --- a/src/utils/SafeCastLib.sol +++ b/src/utils/SafeCastLib.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Safe unsigned integer casting library that reverts on overflow. diff --git a/src/utils/SafeTransferLib.sol b/src/utils/SafeTransferLib.sol index 90d3437d..849bea2f 100644 --- a/src/utils/SafeTransferLib.sol +++ b/src/utils/SafeTransferLib.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; From c608c4cad2b05b85cc115e44358c6130fa432f11 Mon Sep 17 00:00:00 2001 From: t11s Date: Fri, 27 May 2022 12:08:50 -0700 Subject: [PATCH 28/44] 7.0.0-alpha.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index a9f50dbc..152d6576 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@rari-capital/solmate", - "version": "7.0.0-alpha.1", + "version": "7.0.0-alpha.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b481b414..37b08af2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@rari-capital/solmate", "license": "MIT", - "version": "7.0.0-alpha.1", + "version": "7.0.0-alpha.2", "description": "Modern, opinionated and gas optimized building blocks for smart contract development.", "files": [ "src/**/*.sol" From 8f9b23f8838670afda0fd8983f2c41e8037ae6bc Mon Sep 17 00:00:00 2001 From: t11s Date: Wed, 1 Jun 2022 22:56:27 -0700 Subject: [PATCH 29/44] 7.0.0-alpha.3 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 152d6576..4417f323 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@rari-capital/solmate", - "version": "7.0.0-alpha.2", + "version": "7.0.0-alpha.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 37b08af2..2b36b3e1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@rari-capital/solmate", "license": "MIT", - "version": "7.0.0-alpha.2", + "version": "7.0.0-alpha.3", "description": "Modern, opinionated and gas optimized building blocks for smart contract development.", "files": [ "src/**/*.sol" From ee70704f930d81e5994221aacbb3d4c8affaf23f Mon Sep 17 00:00:00 2001 From: t11s Date: Sun, 3 Jul 2022 21:45:07 -0700 Subject: [PATCH 30/44] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Cleanup=20MerkleProo?= =?UTF-8?q?fLib?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/MerkleProof.t.sol | 4 ++-- src/utils/MerkleProof.sol | 40 -------------------------------- src/utils/MerkleProofLib.sol | 44 ++++++++++++++++++++++++++++++++++++ src/utils/SSTORE2.sol | 1 - src/utils/SafeCastLib.sol | 1 - 5 files changed, 46 insertions(+), 44 deletions(-) delete mode 100644 src/utils/MerkleProof.sol create mode 100644 src/utils/MerkleProofLib.sol diff --git a/src/test/MerkleProof.t.sol b/src/test/MerkleProof.t.sol index e3e24bbc..37726f37 100644 --- a/src/test/MerkleProof.t.sol +++ b/src/test/MerkleProof.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.10; import {DSTestPlus} from "./utils/DSTestPlus.sol"; -import {MerkleProof} from "../utils/MerkleProof.sol"; +import {MerkleProofLib} from "../utils/MerkleProofLib.sol"; contract MerkleProofTest is DSTestPlus { function testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() public { @@ -45,6 +45,6 @@ contract MerkleProofTest is DSTestPlus { bytes32 root, bytes32 leaf ) external pure returns (bool) { - return MerkleProof.verify(proof, root, leaf); + return MerkleProofLib.verify(proof, root, leaf); } } diff --git a/src/utils/MerkleProof.sol b/src/utils/MerkleProof.sol deleted file mode 100644 index f79f360f..00000000 --- a/src/utils/MerkleProof.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; - -/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. -/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/MerkleProof.sol) -/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) -library MerkleProof { - function verify( - bytes32[] calldata proof, - bytes32 root, - bytes32 leaf - ) internal pure returns (bool isValid) { - assembly { - let computedHash := leaf - - // Initialize `data` to the offset of `proof` in the calldata. - let data := proof.offset - - // Iterate over proof elements to compute root hash. - for { - // Left shift by 5 is equivalent to multiplying by 0x20. - let end := add(data, shl(5, proof.length)) - } lt(data, end) { - data := add(data, 0x20) - } { - let loadedData := calldataload(data) - // Slot of `computedHash` in scratch space. - // If the condition is true: 0x20, otherwise: 0x00. - let scratch := shl(5, gt(computedHash, loadedData)) - - // Store elements to hash contiguously in scratch space. - // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. - mstore(scratch, computedHash) - mstore(xor(scratch, 0x20), loadedData) - computedHash := keccak256(0x00, 0x40) - } - isValid := eq(computedHash, root) - } - } -} diff --git a/src/utils/MerkleProofLib.sol b/src/utils/MerkleProofLib.sol new file mode 100644 index 00000000..ee3299e8 --- /dev/null +++ b/src/utils/MerkleProofLib.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/// @notice Gas optimized merkle proof verification library. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/MerkleProofLib.sol) +library MerkleProofLib { + function verify( + bytes32[] calldata proof, + bytes32 root, + bytes32 leaf + ) internal pure returns (bool isValid) { + assembly { + let computedHash := leaf // The hash starts as the leaf hash. + + // Initialize data to the offset of the proof in the calldata. + let data := proof.offset + + // Iterate over proof elements to compute root hash. + for { + // Left shifting by 5 is like multiplying by 32. + let end := add(data, shl(5, proof.length)) + } lt(data, end) { + data := add(data, 32) // Shift 1 word per cycle. + } { + // Load the current proof element. + let loadedData := calldataload(data) + + // Slot where computedHash should be put in scratch space. + // If computedHash > loadedData: slot 32, otherwise: slot 0. + let computedHashSlot := shl(5, gt(computedHash, loadedData)) + + // Store elements to hash contiguously in scratch space. + // The xor puts loadedData in whichever slot computedHash is + // not occupying, so 0 if computedHashSlot is 32, 32 otherwise. + mstore(computedHashSlot, computedHash) + mstore(xor(computedHashSlot, 32), loadedData) + + computedHash := keccak256(0, 64) // Hash both slots of scratch space. + } + + isValid := eq(computedHash, root) // The proof is valid if the roots match. + } + } +} diff --git a/src/utils/SSTORE2.sol b/src/utils/SSTORE2.sol index 462bc86a..129b9dac 100644 --- a/src/utils/SSTORE2.sol +++ b/src/utils/SSTORE2.sol @@ -3,7 +3,6 @@ pragma solidity >=0.8.0; /// @notice Read and write to persistent storage at a fraction of the cost. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SSTORE2.sol) -/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol) library SSTORE2 { uint256 internal constant DATA_OFFSET = 1; // We skip the first byte as it's a STOP opcode to ensure the contract can't be called. diff --git a/src/utils/SafeCastLib.sol b/src/utils/SafeCastLib.sol index 030ed020..75c0e726 100644 --- a/src/utils/SafeCastLib.sol +++ b/src/utils/SafeCastLib.sol @@ -3,7 +3,6 @@ pragma solidity >=0.8.0; /// @notice Safe unsigned integer casting library that reverts on overflow. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeCastLib.sol) -/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) library SafeCastLib { function safeCastTo248(uint256 x) internal pure returns (uint248 y) { require(x < 1 << 248); From cfc1d378400b460200d0a9724efcf5a240bd45e8 Mon Sep 17 00:00:00 2001 From: t11s Date: Sun, 4 Sep 2022 10:28:03 -0700 Subject: [PATCH 31/44] =?UTF-8?q?=E2=9C=A8=20New=20[untested]=20FPM=20oper?= =?UTF-8?q?ations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/FixedPointMathLib.sol | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/utils/FixedPointMathLib.sol b/src/utils/FixedPointMathLib.sol index b09d81bb..8fdaa034 100644 --- a/src/utils/FixedPointMathLib.sol +++ b/src/utils/FixedPointMathLib.sol @@ -363,4 +363,26 @@ library FixedPointMathLib { r := or(r, lt(0x1, shr(r, x))) } } + + function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) { + assembly { + // z will equal 0 if y is 0, unlike in Solidity where it will revert. + z := mod(x, y) + } + } + + function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 z) { + assembly { + // z will equal 0 if y is 0, unlike in Solidity where it will revert. + z := div(x, y) + } + } + + /// @dev Will return 0 instead of reverting if y is zero. + function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) { + assembly { + // Add 1 to x * y if x % y > 0. + z := add(gt(mod(x, y), 0), div(x, y)) + } + } } From 02c4fbbbd17c5b1d9c68a2f33e24a9ce02c15f92 Mon Sep 17 00:00:00 2001 From: t11s Date: Sun, 4 Sep 2022 10:32:40 -0700 Subject: [PATCH 32/44] =?UTF-8?q?=E2=9C=A8=20LibERB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/LibERB.sol | 165 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/utils/LibERB.sol diff --git a/src/utils/LibERB.sol b/src/utils/LibERB.sol new file mode 100644 index 00000000..46e912cf --- /dev/null +++ b/src/utils/LibERB.sol @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import {FixedPointMathLib} from "./FixedPointMathLib.sol"; + +// TODO: Does a fixed size array save gas vs a dynamic or mapping? + +// TODO: Prove conjectures about ERB properties with Forge invariants. + +// TODO: Could make this more efficient if we removed availableSlots +// and only allowed grow to be called when index == populatedSlots - 1. + +// TODO: Technically don't need an ERBValue struct? Unless people find +// knowing the writeNumber helpful? It also allows touching the array +// without messing up value in grow tho. If we removed I'd like to add +// the "can't read uninitialized" slots rule back to the read functions. +// I think the best thing to do would be to make it a generic param, +// then if users find it useful they can attach write number, or timestamp, etc. + +/*////////////////////////////////////////////////////////////// + ERB +//////////////////////////////////////////////////////////////*/ + +/// @notice Low-level library for interacting with an expandable ring buffer. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibERB.sol) +library LibERB { + struct ERBValue { + uint224 value; + uint32 writeNumber; + } + + // Expected invariants: + // - availableSlots >= 1 + // - totalWrites >= populatedSlots + // - totalWrites < type(uint32).max + // - availableSlots >= populatedSlots + + function grow( + ERBValue[65535] storage self, + uint16 growBy, + uint16 availableSlots + ) internal returns (uint16 newTotalAvailableSlots) { + // This will overflow if we're trying to grow by too much. + availableSlots = availableSlots + growBy; + + unchecked { + for (uint256 i = availableSlots; i < newTotalAvailableSlots; i++) + // We already implicitly assume we'll never + // reach type(uint32).max many total writes. + self[i].writeNumber = type(uint32).max; + } + } + + function write( + ERBValue[65535] storage self, + uint224 value, + uint32 totalWrites, + uint16 populatedSlots, + uint16 availableSlots // Note: This MUST be at least 1. + ) internal returns (uint32 newTotalWrites, uint16 newPopulatedSlots) { + unchecked { + newPopulatedSlots = populatedSlots == 0 || totalWrites % populatedSlots == (populatedSlots - 1) + ? availableSlots + : populatedSlots; + + newTotalWrites = totalWrites + 1; // This will overflow if we reach type(uint32).max writes. + + self[totalWrites % newPopulatedSlots] = ERBValue({writeNumber: newTotalWrites, value: value}); + } + } + + function read( + ERBValue[65535] storage self, + uint32 totalWrites, + uint16 populatedSlots + ) internal view returns (ERBValue memory) { + // We use unsafeMod so that we use index 0 when populatedSlots is 0. + return self[FixedPointMathLib.unsafeMod(totalWrites, populatedSlots)]; + } + + function readOffset( + ERBValue[65535] storage self, + uint32 offset, + uint32 totalWrites, + uint16 populatedSlots + ) internal view returns (ERBValue memory) { + unchecked { + // We can't read back further than our # of populated slots will allow. + require(offset <= populatedSlots, "OUT_OF_BOUNDS"); + + // We use unsafeMod so that we use index 0 when populatedSlots is 0. + // We assume the invariant totalWrites >= populatedSlots is maintained. + return self[FixedPointMathLib.unsafeMod(totalWrites - offset, populatedSlots)]; + } + } + + function readWriteNumber( + ERBValue[65535] storage self, + uint32 writeNumber, + uint32 totalWrites, + uint16 populatedSlots + ) internal view returns (ERBValue memory) { + // We can't read back further than our # of populated slots will allow. + // This will safely revert due to underflow if writeNumber > totalWrites. + require(totalWrites - writeNumber <= populatedSlots, "OUT_OF_BOUNDS"); + + // Return early if we just wan't the current value. We use + // unsafeMod so that we use index 0 when populatedSlots is 0. + return self[FixedPointMathLib.unsafeMod(writeNumber, populatedSlots)]; + } +} + +/*////////////////////////////////////////////////////////////// + BOXED ERB +//////////////////////////////////////////////////////////////*/ + +/// @notice High-level library for interacting with a self-managing encapsulated ERB. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibERB.sol) +library LibBoxedERB { + struct BoxedERB { + uint32 totalWrites; + uint16 populatedSlots; + uint16 availableSlots; + LibERB.ERBValue[65535] erb; + } + + using LibERB for LibERB.ERBValue[65535]; + + // This should be called once and only + // once over the lifetime of the contract, + // before any calls to write are attempted. + function init(BoxedERB storage self) internal { + self.availableSlots = 1; + + // We already implicitly assume we'll never + // reach type(uint32).max many total writes. + self.erb[0].writeNumber = type(uint32).max; + } + + function grow(BoxedERB storage self, uint16 growBy) internal { + self.availableSlots = self.erb.grow(growBy, self.availableSlots); + } + + // This should only be called if init has been called before. + function write(BoxedERB storage self, uint224 value) internal { + (self.totalWrites, self.populatedSlots) = self.erb.write( + value, + self.totalWrites, + self.populatedSlots, + self.availableSlots + ); + } + + function read(BoxedERB storage self) internal view returns (LibERB.ERBValue memory) { + return self.erb.read(self.totalWrites, self.populatedSlots); + } + + function readOffset(BoxedERB storage self, uint32 offset) internal view returns (LibERB.ERBValue memory) { + return self.erb.readOffset(offset, self.totalWrites, self.populatedSlots); + } + + function readWriteNumber(BoxedERB storage self, uint32 writeNumber) internal view returns (LibERB.ERBValue memory) { + return self.erb.readWriteNumber(writeNumber, self.totalWrites, self.populatedSlots); + } +} From 62c9c9030f657146b5eeec66c642282c2420d87c Mon Sep 17 00:00:00 2001 From: t11s Date: Sun, 4 Sep 2022 11:03:48 -0700 Subject: [PATCH 33/44] =?UTF-8?q?=F0=9F=93=9D=20Cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/LibERB.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/utils/LibERB.sol b/src/utils/LibERB.sol index 46e912cf..a7f602a9 100644 --- a/src/utils/LibERB.sol +++ b/src/utils/LibERB.sol @@ -3,6 +3,8 @@ pragma solidity >=0.8.0; import {FixedPointMathLib} from "./FixedPointMathLib.sol"; +// TODO: Should we return the writeNumber from the read funcs? + // TODO: Does a fixed size array save gas vs a dynamic or mapping? // TODO: Prove conjectures about ERB properties with Forge invariants. @@ -14,8 +16,8 @@ import {FixedPointMathLib} from "./FixedPointMathLib.sol"; // knowing the writeNumber helpful? It also allows touching the array // without messing up value in grow tho. If we removed I'd like to add // the "can't read uninitialized" slots rule back to the read functions. -// I think the best thing to do would be to make it a generic param, -// then if users find it useful they can attach write number, or timestamp, etc. +// I think the best thing to do would be to make it a generic param, then +// if users find it useful they can attach write number, or timestamp, etc. /*////////////////////////////////////////////////////////////// ERB From 6e1b34e7fa359f974fd8030b2a6a2a2e307340e5 Mon Sep 17 00:00:00 2001 From: t11s Date: Sun, 4 Sep 2022 11:13:36 -0700 Subject: [PATCH 34/44] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Terminology=20change?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/LibERB.sol | 68 +++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/src/utils/LibERB.sol b/src/utils/LibERB.sol index a7f602a9..0dbcbd47 100644 --- a/src/utils/LibERB.sol +++ b/src/utils/LibERB.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.0; import {FixedPointMathLib} from "./FixedPointMathLib.sol"; -// TODO: Should we return the writeNumber from the read funcs? +// TODO: Should we return the updateNumber from the read funcs? // TODO: Does a fixed size array save gas vs a dynamic or mapping? @@ -13,11 +13,11 @@ import {FixedPointMathLib} from "./FixedPointMathLib.sol"; // and only allowed grow to be called when index == populatedSlots - 1. // TODO: Technically don't need an ERBValue struct? Unless people find -// knowing the writeNumber helpful? It also allows touching the array +// knowing the updateNumber helpful? It also allows touching the array // without messing up value in grow tho. If we removed I'd like to add // the "can't read uninitialized" slots rule back to the read functions. // I think the best thing to do would be to make it a generic param, then -// if users find it useful they can attach write number, or timestamp, etc. +// if users find it useful they can attach update number, or timestamp, etc. /*////////////////////////////////////////////////////////////// ERB @@ -28,13 +28,13 @@ import {FixedPointMathLib} from "./FixedPointMathLib.sol"; library LibERB { struct ERBValue { uint224 value; - uint32 writeNumber; + uint32 updateNumber; } // Expected invariants: // - availableSlots >= 1 - // - totalWrites >= populatedSlots - // - totalWrites < type(uint32).max + // - totalUpdates >= populatedSlots + // - totalUpdates < type(uint32).max // - availableSlots >= populatedSlots function grow( @@ -48,42 +48,42 @@ library LibERB { unchecked { for (uint256 i = availableSlots; i < newTotalAvailableSlots; i++) // We already implicitly assume we'll never - // reach type(uint32).max many total writes. - self[i].writeNumber = type(uint32).max; + // reach type(uint32).max many total updates. + self[i].updateNumber = type(uint32).max; } } function write( ERBValue[65535] storage self, uint224 value, - uint32 totalWrites, + uint32 totalUpdates, uint16 populatedSlots, uint16 availableSlots // Note: This MUST be at least 1. - ) internal returns (uint32 newTotalWrites, uint16 newPopulatedSlots) { + ) internal returns (uint32 newTotalUpdates, uint16 newPopulatedSlots) { unchecked { - newPopulatedSlots = populatedSlots == 0 || totalWrites % populatedSlots == (populatedSlots - 1) + newPopulatedSlots = populatedSlots == 0 || totalUpdates % populatedSlots == (populatedSlots - 1) ? availableSlots : populatedSlots; - newTotalWrites = totalWrites + 1; // This will overflow if we reach type(uint32).max writes. + newTotalUpdates = totalUpdates + 1; // This will overflow if we reach type(uint32).max updates. - self[totalWrites % newPopulatedSlots] = ERBValue({writeNumber: newTotalWrites, value: value}); + self[totalUpdates % newPopulatedSlots] = ERBValue({value: value, updateNumber: newTotalUpdates}); } } function read( ERBValue[65535] storage self, - uint32 totalWrites, + uint32 totalUpdates, uint16 populatedSlots ) internal view returns (ERBValue memory) { // We use unsafeMod so that we use index 0 when populatedSlots is 0. - return self[FixedPointMathLib.unsafeMod(totalWrites, populatedSlots)]; + return self[FixedPointMathLib.unsafeMod(totalUpdates, populatedSlots)]; } function readOffset( ERBValue[65535] storage self, uint32 offset, - uint32 totalWrites, + uint32 totalUpdates, uint16 populatedSlots ) internal view returns (ERBValue memory) { unchecked { @@ -91,24 +91,24 @@ library LibERB { require(offset <= populatedSlots, "OUT_OF_BOUNDS"); // We use unsafeMod so that we use index 0 when populatedSlots is 0. - // We assume the invariant totalWrites >= populatedSlots is maintained. - return self[FixedPointMathLib.unsafeMod(totalWrites - offset, populatedSlots)]; + // We assume the invariant totalUpdates >= populatedSlots is maintained. + return self[FixedPointMathLib.unsafeMod(totalUpdates - offset, populatedSlots)]; } } function readWriteNumber( ERBValue[65535] storage self, - uint32 writeNumber, - uint32 totalWrites, + uint32 updateNumber, + uint32 totalUpdates, uint16 populatedSlots ) internal view returns (ERBValue memory) { // We can't read back further than our # of populated slots will allow. - // This will safely revert due to underflow if writeNumber > totalWrites. - require(totalWrites - writeNumber <= populatedSlots, "OUT_OF_BOUNDS"); + // This will safely revert due to underflow if updateNumber > totalUpdates. + require(totalUpdates - updateNumber <= populatedSlots, "OUT_OF_BOUNDS"); // Return early if we just wan't the current value. We use // unsafeMod so that we use index 0 when populatedSlots is 0. - return self[FixedPointMathLib.unsafeMod(writeNumber, populatedSlots)]; + return self[FixedPointMathLib.unsafeMod(updateNumber, populatedSlots)]; } } @@ -120,7 +120,7 @@ library LibERB { /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibERB.sol) library LibBoxedERB { struct BoxedERB { - uint32 totalWrites; + uint32 totalUpdates; uint16 populatedSlots; uint16 availableSlots; LibERB.ERBValue[65535] erb; @@ -135,8 +135,8 @@ library LibBoxedERB { self.availableSlots = 1; // We already implicitly assume we'll never - // reach type(uint32).max many total writes. - self.erb[0].writeNumber = type(uint32).max; + // reach type(uint32).max many total updates. + self.erb[0].updateNumber = type(uint32).max; } function grow(BoxedERB storage self, uint16 growBy) internal { @@ -145,23 +145,27 @@ library LibBoxedERB { // This should only be called if init has been called before. function write(BoxedERB storage self, uint224 value) internal { - (self.totalWrites, self.populatedSlots) = self.erb.write( + (self.totalUpdates, self.populatedSlots) = self.erb.write( value, - self.totalWrites, + self.totalUpdates, self.populatedSlots, self.availableSlots ); } function read(BoxedERB storage self) internal view returns (LibERB.ERBValue memory) { - return self.erb.read(self.totalWrites, self.populatedSlots); + return self.erb.read(self.totalUpdates, self.populatedSlots); } function readOffset(BoxedERB storage self, uint32 offset) internal view returns (LibERB.ERBValue memory) { - return self.erb.readOffset(offset, self.totalWrites, self.populatedSlots); + return self.erb.readOffset(offset, self.totalUpdates, self.populatedSlots); } - function readWriteNumber(BoxedERB storage self, uint32 writeNumber) internal view returns (LibERB.ERBValue memory) { - return self.erb.readWriteNumber(writeNumber, self.totalWrites, self.populatedSlots); + function readWriteNumber(BoxedERB storage self, uint32 updateNumber) + internal + view + returns (LibERB.ERBValue memory) + { + return self.erb.readWriteNumber(updateNumber, self.totalUpdates, self.populatedSlots); } } From 6b6f11dd1f4564eddc887f3ce74caaa03741624f Mon Sep 17 00:00:00 2001 From: t11s Date: Sun, 4 Sep 2022 11:16:11 -0700 Subject: [PATCH 35/44] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20More=20renaming?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/LibERB.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/LibERB.sol b/src/utils/LibERB.sol index 0dbcbd47..7956e83d 100644 --- a/src/utils/LibERB.sol +++ b/src/utils/LibERB.sol @@ -96,7 +96,7 @@ library LibERB { } } - function readWriteNumber( + function readUpdateNumber( ERBValue[65535] storage self, uint32 updateNumber, uint32 totalUpdates, @@ -161,11 +161,11 @@ library LibBoxedERB { return self.erb.readOffset(offset, self.totalUpdates, self.populatedSlots); } - function readWriteNumber(BoxedERB storage self, uint32 updateNumber) + function readUpdateNumber(BoxedERB storage self, uint32 updateNumber) internal view returns (LibERB.ERBValue memory) { - return self.erb.readWriteNumber(updateNumber, self.totalUpdates, self.populatedSlots); + return self.erb.readUpdateNumber(updateNumber, self.totalUpdates, self.populatedSlots); } } From 4933263adeb62ee8878028e542453c4d1a071be9 Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 8 Sep 2022 00:08:47 -0700 Subject: [PATCH 36/44] wip --- src/test/LibERB.t.sol | 80 +++++++++++++++++++++++++++++++++++++++++++ src/utils/LibERB.sol | 12 ++++--- 2 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 src/test/LibERB.t.sol diff --git a/src/test/LibERB.t.sol b/src/test/LibERB.t.sol new file mode 100644 index 00000000..7c4f52fd --- /dev/null +++ b/src/test/LibERB.t.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.10; + +import {DSTestPlus} from "./utils/DSTestPlus.sol"; + +import {LibERB, LibBoxedERB} from "../utils/LibERB.sol"; + +contract BoxedERBInvariants is DSTestPlus { + using LibBoxedERB for LibBoxedERB.BoxedERB; + + BoxedERB boxedERB; + + function setUp() public { + boxedERB = new BoxedERB(); + } + + function testReproduce() public { + boxedERB.grow(10); + + emit log_uint(boxedERB.availableSlots()); + emit log_uint(boxedERB.populatedSlots()); + + boxedERB.write(1); + + emit log_uint(boxedERB.availableSlots()); + emit log_uint(boxedERB.populatedSlots()); + + require(boxedERB.read().updateNumber - 1 == boxedERB.readOffset(1).updateNumber); + } + + function invariantMonotonicUpdateNumber() public { + if (boxedERB.populatedSlots() < 2) return; + + emit log_uint(boxedERB.read().updateNumber - 1); + emit log_uint(boxedERB.readOffset(1).updateNumber); + + require(boxedERB.read().updateNumber - 1 == boxedERB.readOffset(1).updateNumber); + } + + function invariantPopulatedSlotsLeToAvailable() public { + emit log_uint(boxedERB.populatedSlots()); + emit log_uint(boxedERB.availableSlots()); + require(boxedERB.populatedSlots() <= boxedERB.availableSlots()); + // assertLe(boxedERB.populatedSlots(), boxedERB.availableSlots()); + } +} + +contract BoxedERB { + using LibBoxedERB for LibBoxedERB.BoxedERB; + + LibBoxedERB.BoxedERB public boxedERB; + + constructor() { + boxedERB.init(); + } + + function write(uint224 x) public { + boxedERB.write(x); + } + + function grow(uint16 growBy) public { + boxedERB.grow(growBy); + } + + function read() public view returns (LibERB.ERBValue memory) { + return boxedERB.read(); + } + + function readOffset(uint32 offset) public view returns (LibERB.ERBValue memory) { + return boxedERB.readOffset(offset); + } + + function populatedSlots() public view returns (uint256) { + return boxedERB.populatedSlots; + } + + function availableSlots() public view returns (uint256) { + return boxedERB.availableSlots; + } +} diff --git a/src/utils/LibERB.sol b/src/utils/LibERB.sol index 7956e83d..2cb41a2d 100644 --- a/src/utils/LibERB.sol +++ b/src/utils/LibERB.sol @@ -43,7 +43,7 @@ library LibERB { uint16 availableSlots ) internal returns (uint16 newTotalAvailableSlots) { // This will overflow if we're trying to grow by too much. - availableSlots = availableSlots + growBy; + newTotalAvailableSlots = availableSlots + growBy; unchecked { for (uint256 i = availableSlots; i < newTotalAvailableSlots; i++) @@ -61,11 +61,15 @@ library LibERB { uint16 availableSlots // Note: This MUST be at least 1. ) internal returns (uint32 newTotalUpdates, uint16 newPopulatedSlots) { unchecked { - newPopulatedSlots = populatedSlots == 0 || totalUpdates % populatedSlots == (populatedSlots - 1) - ? availableSlots + // TODO: hmm ok we also need to make sure we dont exceed available slots + // TODO: wait why do we even need to do this??? + // TODO: also wait confused about the root cause, why does poulpated slots matter again + newPopulatedSlots = populatedSlots == 0 || + (totalUpdates % populatedSlots == (populatedSlots - 1) && populatedSlots < availableSlots) + ? populatedSlots + 1 : populatedSlots; - newTotalUpdates = totalUpdates + 1; // This will overflow if we reach type(uint32).max updates. + newTotalUpdates = totalUpdates + 1; // This will silently overflow if we reach type(uint32).max updates. self[totalUpdates % newPopulatedSlots] = ERBValue({value: value, updateNumber: newTotalUpdates}); } From b9d69da49bbbfd090f1a73a4dba28aa2d5ee199f Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 23 Sep 2022 17:10:40 -0400 Subject: [PATCH 37/44] =?UTF-8?q?=F0=9F=93=9D=20Update=20LICENSE=20(#325)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: t11s --- LICENSE | 682 ++------------------------------------------------------ 1 file changed, 21 insertions(+), 661 deletions(-) diff --git a/LICENSE b/LICENSE index 29ebfa54..64690f06 100644 --- a/LICENSE +++ b/LICENSE @@ -1,661 +1,21 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. \ No newline at end of file +MIT License + +Copyright (c) 2022 t11s + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From ed67feda67b24fdeff8ad1032360f0ee6047ba0a Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 29 Sep 2022 03:38:28 -0400 Subject: [PATCH 38/44] =?UTF-8?q?=F0=9F=93=9D=20Make=20Owned.sol=20MIT=20l?= =?UTF-8?q?icensed=20too=20(#328)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/auth/Owned.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth/Owned.sol b/src/auth/Owned.sol index 415d845b..ef8b1bad 100644 --- a/src/auth/Owned.sol +++ b/src/auth/Owned.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. From e8f96f25d48fe702117ce76c79228ca4f20206cb Mon Sep 17 00:00:00 2001 From: Pascal Marco Caversaccio Date: Wed, 5 Apr 2023 20:13:27 +0200 Subject: [PATCH 39/44] =?UTF-8?q?=F0=9F=93=9D=20Fix=20comments=20on=20RLP?= =?UTF-8?q?=20encoding=20scheme=20(#301)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✍️ correct comment on RLP encoding scheme * corrected comments * adjust comment on max account nonce * Update src/utils/LibRLP.sol * Update src/utils/LibRLP.sol * Update src/utils/LibRLP.sol * Update src/utils/LibRLP.sol --------- Co-authored-by: t11s --- src/utils/LibRLP.sol | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/utils/LibRLP.sol b/src/utils/LibRLP.sol index 6435f15e..6caec02a 100644 --- a/src/utils/LibRLP.sol +++ b/src/utils/LibRLP.sol @@ -10,21 +10,26 @@ library LibRLP { // prettier-ignore function computeAddress(address deployer, uint256 nonce) internal pure returns (address) { + // The theoretical allowed limit, based on EIP-2681, for an account nonce is 2**64-2: https://eips.ethereum.org/EIPS/eip-2681. + // However, we assume nobody can have a nonce large enough to require more than 4 bytes. + // Thus, no specific check is built-in to save deployment costs. + // 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 keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))).fromLast20Bytes(); + + // A one-byte integer in the [0x00, 0x7f] range uses its own value as a length prefix, there is no additional "0x80 + length" prefix that precedes it. if (nonce <= 0x7f) return keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))).fromLast20Bytes(); - // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length. + // In the case of nonce > 0x7f and nonce <= type(uint8).max, we have the following + // encoding scheme (the same calculation can be carried over for higher nonce bytes): + // 0xda = 0xc0 (short RLP prefix) + 0x1a (= the bytes length of: 0x94 + address + 0x84 + nonce, in hex), + // 0x94 = 0x80 + 0x14 (= the bytes length of an address, 20 bytes, in hex), + // 0x84 = 0x80 + 0x04 (= the bytes length of the nonce, 4 bytes, in hex). if (nonce <= type(uint8).max) return keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))).fromLast20Bytes(); if (nonce <= type(uint16).max) return keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))).fromLast20Bytes(); if (nonce <= type(uint24).max) return keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))).fromLast20Bytes(); - // 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. + // Case for nonce > uint24 and nonce <= type(uint32).max. return keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))).fromLast20Bytes(); } } From 27bcd5126da617d2c5041cdcbacce26108cf8e3d Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 8 Feb 2024 16:37:06 -0800 Subject: [PATCH 40/44] =?UTF-8?q?=F0=9F=94=A5=20Remove=20LibERB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Has too many bugs I don't want to look into right now. --- src/test/LibERB.t.sol | 80 ------------------- src/utils/LibERB.sol | 175 ------------------------------------------ 2 files changed, 255 deletions(-) delete mode 100644 src/test/LibERB.t.sol delete mode 100644 src/utils/LibERB.sol diff --git a/src/test/LibERB.t.sol b/src/test/LibERB.t.sol deleted file mode 100644 index 7c4f52fd..00000000 --- a/src/test/LibERB.t.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.10; - -import {DSTestPlus} from "./utils/DSTestPlus.sol"; - -import {LibERB, LibBoxedERB} from "../utils/LibERB.sol"; - -contract BoxedERBInvariants is DSTestPlus { - using LibBoxedERB for LibBoxedERB.BoxedERB; - - BoxedERB boxedERB; - - function setUp() public { - boxedERB = new BoxedERB(); - } - - function testReproduce() public { - boxedERB.grow(10); - - emit log_uint(boxedERB.availableSlots()); - emit log_uint(boxedERB.populatedSlots()); - - boxedERB.write(1); - - emit log_uint(boxedERB.availableSlots()); - emit log_uint(boxedERB.populatedSlots()); - - require(boxedERB.read().updateNumber - 1 == boxedERB.readOffset(1).updateNumber); - } - - function invariantMonotonicUpdateNumber() public { - if (boxedERB.populatedSlots() < 2) return; - - emit log_uint(boxedERB.read().updateNumber - 1); - emit log_uint(boxedERB.readOffset(1).updateNumber); - - require(boxedERB.read().updateNumber - 1 == boxedERB.readOffset(1).updateNumber); - } - - function invariantPopulatedSlotsLeToAvailable() public { - emit log_uint(boxedERB.populatedSlots()); - emit log_uint(boxedERB.availableSlots()); - require(boxedERB.populatedSlots() <= boxedERB.availableSlots()); - // assertLe(boxedERB.populatedSlots(), boxedERB.availableSlots()); - } -} - -contract BoxedERB { - using LibBoxedERB for LibBoxedERB.BoxedERB; - - LibBoxedERB.BoxedERB public boxedERB; - - constructor() { - boxedERB.init(); - } - - function write(uint224 x) public { - boxedERB.write(x); - } - - function grow(uint16 growBy) public { - boxedERB.grow(growBy); - } - - function read() public view returns (LibERB.ERBValue memory) { - return boxedERB.read(); - } - - function readOffset(uint32 offset) public view returns (LibERB.ERBValue memory) { - return boxedERB.readOffset(offset); - } - - function populatedSlots() public view returns (uint256) { - return boxedERB.populatedSlots; - } - - function availableSlots() public view returns (uint256) { - return boxedERB.availableSlots; - } -} diff --git a/src/utils/LibERB.sol b/src/utils/LibERB.sol deleted file mode 100644 index 2cb41a2d..00000000 --- a/src/utils/LibERB.sol +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; - -import {FixedPointMathLib} from "./FixedPointMathLib.sol"; - -// TODO: Should we return the updateNumber from the read funcs? - -// TODO: Does a fixed size array save gas vs a dynamic or mapping? - -// TODO: Prove conjectures about ERB properties with Forge invariants. - -// TODO: Could make this more efficient if we removed availableSlots -// and only allowed grow to be called when index == populatedSlots - 1. - -// TODO: Technically don't need an ERBValue struct? Unless people find -// knowing the updateNumber helpful? It also allows touching the array -// without messing up value in grow tho. If we removed I'd like to add -// the "can't read uninitialized" slots rule back to the read functions. -// I think the best thing to do would be to make it a generic param, then -// if users find it useful they can attach update number, or timestamp, etc. - -/*////////////////////////////////////////////////////////////// - ERB -//////////////////////////////////////////////////////////////*/ - -/// @notice Low-level library for interacting with an expandable ring buffer. -/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibERB.sol) -library LibERB { - struct ERBValue { - uint224 value; - uint32 updateNumber; - } - - // Expected invariants: - // - availableSlots >= 1 - // - totalUpdates >= populatedSlots - // - totalUpdates < type(uint32).max - // - availableSlots >= populatedSlots - - function grow( - ERBValue[65535] storage self, - uint16 growBy, - uint16 availableSlots - ) internal returns (uint16 newTotalAvailableSlots) { - // This will overflow if we're trying to grow by too much. - newTotalAvailableSlots = availableSlots + growBy; - - unchecked { - for (uint256 i = availableSlots; i < newTotalAvailableSlots; i++) - // We already implicitly assume we'll never - // reach type(uint32).max many total updates. - self[i].updateNumber = type(uint32).max; - } - } - - function write( - ERBValue[65535] storage self, - uint224 value, - uint32 totalUpdates, - uint16 populatedSlots, - uint16 availableSlots // Note: This MUST be at least 1. - ) internal returns (uint32 newTotalUpdates, uint16 newPopulatedSlots) { - unchecked { - // TODO: hmm ok we also need to make sure we dont exceed available slots - // TODO: wait why do we even need to do this??? - // TODO: also wait confused about the root cause, why does poulpated slots matter again - newPopulatedSlots = populatedSlots == 0 || - (totalUpdates % populatedSlots == (populatedSlots - 1) && populatedSlots < availableSlots) - ? populatedSlots + 1 - : populatedSlots; - - newTotalUpdates = totalUpdates + 1; // This will silently overflow if we reach type(uint32).max updates. - - self[totalUpdates % newPopulatedSlots] = ERBValue({value: value, updateNumber: newTotalUpdates}); - } - } - - function read( - ERBValue[65535] storage self, - uint32 totalUpdates, - uint16 populatedSlots - ) internal view returns (ERBValue memory) { - // We use unsafeMod so that we use index 0 when populatedSlots is 0. - return self[FixedPointMathLib.unsafeMod(totalUpdates, populatedSlots)]; - } - - function readOffset( - ERBValue[65535] storage self, - uint32 offset, - uint32 totalUpdates, - uint16 populatedSlots - ) internal view returns (ERBValue memory) { - unchecked { - // We can't read back further than our # of populated slots will allow. - require(offset <= populatedSlots, "OUT_OF_BOUNDS"); - - // We use unsafeMod so that we use index 0 when populatedSlots is 0. - // We assume the invariant totalUpdates >= populatedSlots is maintained. - return self[FixedPointMathLib.unsafeMod(totalUpdates - offset, populatedSlots)]; - } - } - - function readUpdateNumber( - ERBValue[65535] storage self, - uint32 updateNumber, - uint32 totalUpdates, - uint16 populatedSlots - ) internal view returns (ERBValue memory) { - // We can't read back further than our # of populated slots will allow. - // This will safely revert due to underflow if updateNumber > totalUpdates. - require(totalUpdates - updateNumber <= populatedSlots, "OUT_OF_BOUNDS"); - - // Return early if we just wan't the current value. We use - // unsafeMod so that we use index 0 when populatedSlots is 0. - return self[FixedPointMathLib.unsafeMod(updateNumber, populatedSlots)]; - } -} - -/*////////////////////////////////////////////////////////////// - BOXED ERB -//////////////////////////////////////////////////////////////*/ - -/// @notice High-level library for interacting with a self-managing encapsulated ERB. -/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibERB.sol) -library LibBoxedERB { - struct BoxedERB { - uint32 totalUpdates; - uint16 populatedSlots; - uint16 availableSlots; - LibERB.ERBValue[65535] erb; - } - - using LibERB for LibERB.ERBValue[65535]; - - // This should be called once and only - // once over the lifetime of the contract, - // before any calls to write are attempted. - function init(BoxedERB storage self) internal { - self.availableSlots = 1; - - // We already implicitly assume we'll never - // reach type(uint32).max many total updates. - self.erb[0].updateNumber = type(uint32).max; - } - - function grow(BoxedERB storage self, uint16 growBy) internal { - self.availableSlots = self.erb.grow(growBy, self.availableSlots); - } - - // This should only be called if init has been called before. - function write(BoxedERB storage self, uint224 value) internal { - (self.totalUpdates, self.populatedSlots) = self.erb.write( - value, - self.totalUpdates, - self.populatedSlots, - self.availableSlots - ); - } - - function read(BoxedERB storage self) internal view returns (LibERB.ERBValue memory) { - return self.erb.read(self.totalUpdates, self.populatedSlots); - } - - function readOffset(BoxedERB storage self, uint32 offset) internal view returns (LibERB.ERBValue memory) { - return self.erb.readOffset(offset, self.totalUpdates, self.populatedSlots); - } - - function readUpdateNumber(BoxedERB storage self, uint32 updateNumber) - internal - view - returns (LibERB.ERBValue memory) - { - return self.erb.readUpdateNumber(updateNumber, self.totalUpdates, self.populatedSlots); - } -} From c3051c92b9ba7c54a9dd1b686305190ee8dd2a11 Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 8 Feb 2024 16:41:21 -0800 Subject: [PATCH 41/44] =?UTF-8?q?=F0=9F=91=B7=E2=80=8D=E2=99=82=EF=B8=8F?= =?UTF-8?q?=20Upgrade=20to=200.8.24=20+=20Cancun=20(#408)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- foundry.toml | 7 ++++--- src/test/Auth.t.sol | 2 +- src/test/Bytes32AddressLib.t.sol | 2 +- src/test/CREATE3.t.sol | 2 +- src/test/DSTestPlus.t.sol | 2 +- src/test/ERC1155.t.sol | 2 +- src/test/ERC1155B.t.sol | 2 +- src/test/ERC20.t.sol | 2 +- src/test/ERC4626.t.sol | 2 +- src/test/ERC721.t.sol | 2 +- src/test/FixedPointMathLib.t.sol | 2 +- src/test/LibBitmap.t.sol | 2 +- src/test/MerkleProof.t.sol | 2 +- src/test/MultiRolesAuthority.t.sol | 2 +- src/test/Owned.t.sol | 2 +- src/test/ReentrancyGuard.t.sol | 2 +- src/test/RolesAuthority.t.sol | 2 +- src/test/SSTORE2.t.sol | 2 +- src/test/SafeCastLib.t.sol | 2 +- src/test/SafeTransferLib.t.sol | 2 +- src/test/WETH.t.sol | 2 +- 21 files changed, 24 insertions(+), 23 deletions(-) diff --git a/foundry.toml b/foundry.toml index 8a4fd22d..c130d617 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,7 +1,8 @@ -[default] -solc = "0.8.10" +[profile.default] +solc = "0.8.24" +evm_version = "cancun" bytecode_hash = "none" optimizer_runs = 1000000 -[intense] +[profile.intense] fuzz_runs = 10000 diff --git a/src/test/Auth.t.sol b/src/test/Auth.t.sol index 00e29ccf..0af8695c 100644 --- a/src/test/Auth.t.sol +++ b/src/test/Auth.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {MockAuthChild} from "./utils/mocks/MockAuthChild.sol"; diff --git a/src/test/Bytes32AddressLib.t.sol b/src/test/Bytes32AddressLib.t.sol index 50d8f971..da6e2667 100644 --- a/src/test/Bytes32AddressLib.t.sol +++ b/src/test/Bytes32AddressLib.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/CREATE3.t.sol b/src/test/CREATE3.t.sol index 64e25751..864b9592 100644 --- a/src/test/CREATE3.t.sol +++ b/src/test/CREATE3.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {WETH} from "../tokens/WETH.sol"; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/DSTestPlus.t.sol b/src/test/DSTestPlus.t.sol index 4842abf8..b5077a38 100644 --- a/src/test/DSTestPlus.t.sol +++ b/src/test/DSTestPlus.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/ERC1155.t.sol b/src/test/ERC1155.t.sol index dd76a494..ee724427 100644 --- a/src/test/ERC1155.t.sol +++ b/src/test/ERC1155.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {DSInvariantTest} from "./utils/DSInvariantTest.sol"; diff --git a/src/test/ERC1155B.t.sol b/src/test/ERC1155B.t.sol index 014e4094..99de0aa6 100644 --- a/src/test/ERC1155B.t.sol +++ b/src/test/ERC1155B.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {DSInvariantTest} from "./utils/DSInvariantTest.sol"; diff --git a/src/test/ERC20.t.sol b/src/test/ERC20.t.sol index 530a8b2d..791537d9 100644 --- a/src/test/ERC20.t.sol +++ b/src/test/ERC20.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {DSInvariantTest} from "./utils/DSInvariantTest.sol"; diff --git a/src/test/ERC4626.t.sol b/src/test/ERC4626.t.sol index 3c143a96..e2270aec 100644 --- a/src/test/ERC4626.t.sol +++ b/src/test/ERC4626.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/ERC721.t.sol b/src/test/ERC721.t.sol index d0d87a66..571a133e 100644 --- a/src/test/ERC721.t.sol +++ b/src/test/ERC721.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {DSInvariantTest} from "./utils/DSInvariantTest.sol"; diff --git a/src/test/FixedPointMathLib.t.sol b/src/test/FixedPointMathLib.t.sol index d8e71765..3af55009 100644 --- a/src/test/FixedPointMathLib.t.sol +++ b/src/test/FixedPointMathLib.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/LibBitmap.t.sol b/src/test/LibBitmap.t.sol index 7ef65230..ef59f24c 100644 --- a/src/test/LibBitmap.t.sol +++ b/src/test/LibBitmap.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/MerkleProof.t.sol b/src/test/MerkleProof.t.sol index 37726f37..2eb4714c 100644 --- a/src/test/MerkleProof.t.sol +++ b/src/test/MerkleProof.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/MultiRolesAuthority.t.sol b/src/test/MultiRolesAuthority.t.sol index 65031923..823ea2a2 100644 --- a/src/test/MultiRolesAuthority.t.sol +++ b/src/test/MultiRolesAuthority.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {MockAuthority} from "./utils/mocks/MockAuthority.sol"; diff --git a/src/test/Owned.t.sol b/src/test/Owned.t.sol index 6c30c103..5d30f92d 100644 --- a/src/test/Owned.t.sol +++ b/src/test/Owned.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: AGPL-3.0-only -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {MockOwned} from "./utils/mocks/MockOwned.sol"; diff --git a/src/test/ReentrancyGuard.t.sol b/src/test/ReentrancyGuard.t.sol index 048426f4..a24f56af 100644 --- a/src/test/ReentrancyGuard.t.sol +++ b/src/test/ReentrancyGuard.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/RolesAuthority.t.sol b/src/test/RolesAuthority.t.sol index 6c36cb3e..5091f883 100644 --- a/src/test/RolesAuthority.t.sol +++ b/src/test/RolesAuthority.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {MockAuthority} from "./utils/mocks/MockAuthority.sol"; diff --git a/src/test/SSTORE2.t.sol b/src/test/SSTORE2.t.sol index c9f9fd0b..377bf2fc 100644 --- a/src/test/SSTORE2.t.sol +++ b/src/test/SSTORE2.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/SafeCastLib.t.sol b/src/test/SafeCastLib.t.sol index b97b244b..b9b606ad 100644 --- a/src/test/SafeCastLib.t.sol +++ b/src/test/SafeCastLib.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/SafeTransferLib.t.sol b/src/test/SafeTransferLib.t.sol index 8bed492e..350c09ea 100644 --- a/src/test/SafeTransferLib.t.sol +++ b/src/test/SafeTransferLib.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {MockERC20} from "./utils/mocks/MockERC20.sol"; import {RevertingToken} from "./utils/weird-tokens/RevertingToken.sol"; diff --git a/src/test/WETH.t.sol b/src/test/WETH.t.sol index 8bcb86b0..53299c20 100644 --- a/src/test/WETH.t.sol +++ b/src/test/WETH.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.10; +pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; import {DSInvariantTest} from "./utils/DSInvariantTest.sol"; From 1be9d310593a49b1fa42057d066bc2529a7ea68f Mon Sep 17 00:00:00 2001 From: t11s Date: Thu, 8 Feb 2024 17:48:46 -0800 Subject: [PATCH 42/44] =?UTF-8?q?=F0=9F=91=B7=E2=80=8D=E2=99=82=EF=B8=8F?= =?UTF-8?q?=20Licensing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/Owned.t.sol | 2 +- src/test/utils/mocks/MockOwned.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/Owned.t.sol b/src/test/Owned.t.sol index 5d30f92d..495084af 100644 --- a/src/test/Owned.t.sol +++ b/src/test/Owned.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {DSTestPlus} from "./utils/DSTestPlus.sol"; diff --git a/src/test/utils/mocks/MockOwned.sol b/src/test/utils/mocks/MockOwned.sol index 52ef918e..6a501054 100644 --- a/src/test/utils/mocks/MockOwned.sol +++ b/src/test/utils/mocks/MockOwned.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {Owned} from "../../../auth/Owned.sol"; From aebc05f1e440c95a4a3c70486ad1183e715692fd Mon Sep 17 00:00:00 2001 From: t11s Date: Fri, 9 Feb 2024 17:40:08 -0800 Subject: [PATCH 43/44] =?UTF-8?q?=E2=9C=A8=20Transient=20Reentrancy=20Guar?= =?UTF-8?q?d=20(#409)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 761 +++++++++++++++--------- src/test/TransientReentrancyGuard.t.sol | 52 ++ src/utils/TransientReentrancyGuard.sol | 39 ++ 3 files changed, 580 insertions(+), 272 deletions(-) create mode 100644 src/test/TransientReentrancyGuard.t.sol create mode 100644 src/utils/TransientReentrancyGuard.sol diff --git a/.gas-snapshot b/.gas-snapshot index fbb08090..ca897148 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,274 +1,491 @@ -AuthTest:testCallFunctionAsOwner() (gas: 29828) -AuthTest:testCallFunctionWithPermissiveAuthority() (gas: 124270) -AuthTest:testFailCallFunctionAsNonOwner() (gas: 15491) -AuthTest:testFailCallFunctionAsOwnerWithOutOfOrderAuthority() (gas: 136042) -AuthTest:testFailCallFunctionWithRestrictiveAuthority() (gas: 129178) -AuthTest:testFailSetAuthorityAsNonOwner() (gas: 18304) -AuthTest:testFailSetAuthorityWithRestrictiveAuthority() (gas: 129078) -AuthTest:testFailSetOwnerAsNonOwner() (gas: 15587) -AuthTest:testFailSetOwnerAsOwnerWithOutOfOrderAuthority() (gas: 136118) -AuthTest:testFailSetOwnerWithRestrictiveAuthority() (gas: 129264) -AuthTest:testSetAuthorityAsOwner() (gas: 32235) -AuthTest:testSetAuthorityAsOwnerWithOutOfOrderAuthority() (gas: 226463) -AuthTest:testSetAuthorityWithPermissiveAuthority() (gas: 125918) -AuthTest:testSetOwnerAsOwner() (gas: 15276) -AuthTest:testSetOwnerWithPermissiveAuthority() (gas: 127906) -Bytes32AddressLibTest:testFillLast12Bytes() (gas: 223) -Bytes32AddressLibTest:testFromLast20Bytes() (gas: 191) -CREATE3Test:testDeployERC20() (gas: 852410) -CREATE3Test:testFailDoubleDeployDifferentBytecode() (gas: 9079256848778914164) -CREATE3Test:testFailDoubleDeploySameBytecode() (gas: 9079256848778906218) -DSTestPlusTest:testBound() (gas: 14208) -DSTestPlusTest:testBrutalizeMemory() (gas: 823) -DSTestPlusTest:testFailBoundMinBiggerThanMax() (gas: 287) -DSTestPlusTest:testMeasuringGas() (gas: 24600) -DSTestPlusTest:testRelApproxEqBothZeroesPasses() (gas: 391) -ERC1155Test:testApproveAll() (gas: 31053) -ERC1155Test:testBatchBalanceOf() (gas: 157552) -ERC1155Test:testBatchBurn() (gas: 151044) -ERC1155Test:testBatchMintToEOA() (gas: 137286) -ERC1155Test:testBatchMintToERC1155Recipient() (gas: 942660) -ERC1155Test:testBurn() (gas: 38569) -ERC1155Test:testFailBalanceOfBatchWithArrayMismatch() (gas: 7933) -ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136170) -ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 135536) -ERC1155Test:testFailBatchMintToNonERC1155Recipient() (gas: 167311) -ERC1155Test:testFailBatchMintToRevertingERC1155Recipient() (gas: 358854) -ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 310733) -ERC1155Test:testFailBatchMintToZero() (gas: 131709) -ERC1155Test:testFailBatchMintWithArrayMismatch() (gas: 9621) -ERC1155Test:testFailBurnInsufficientBalance() (gas: 34823) -ERC1155Test:testFailMintToNonERC155Recipient() (gas: 68192) -ERC1155Test:testFailMintToRevertingERC155Recipient() (gas: 259413) -ERC1155Test:testFailMintToWrongReturnDataERC155Recipient() (gas: 259412) -ERC1155Test:testFailMintToZero() (gas: 33698) -ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 321348) -ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 512927) -ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 464850) -ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 286521) -ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 162646) -ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 163526) -ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 63260) -ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance() (gas: 34320) -ERC1155Test:testFailSafeTransferFromToNonERC155Recipient() (gas: 96510) -ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 287732) -ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 239598) -ERC1155Test:testFailSafeTransferFromToZero() (gas: 62007) -ERC1155Test:testMintToEOA() (gas: 34736) -ERC1155Test:testMintToERC1155Recipient() (gas: 608327) -ERC1155Test:testSafeBatchTransferFromToEOA() (gas: 297808) -ERC1155Test:testSafeBatchTransferFromToERC1155Recipient() (gas: 1122267) -ERC1155Test:testSafeTransferFromSelf() (gas: 64148) -ERC1155Test:testSafeTransferFromToEOA() (gas: 93154) -ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 686493) -ERC1155BTest:testApproveAll() (gas: 30947) -ERC1155BTest:testBatchBalanceOf() (gas: 157205) -ERC1155BTest:testBatchBurn() (gas: 114460) -ERC1155BTest:testBatchMintToEOA() (gas: 135755) -ERC1155BTest:testBatchMintToERC1155Recipient() (gas: 941538) -ERC1155BTest:testBurn() (gas: 26502) -ERC1155BTest:testFailBalanceOfBatchWithArrayMismatch() (gas: 7933) -ERC1155BTest:testFailBatchBurnInsufficientBalance() (gas: 10052) -ERC1155BTest:testFailBatchMintToNonERC1155Recipient() (gas: 166023) -ERC1155BTest:testFailBatchMintToRevertingERC1155Recipient() (gas: 357584) -ERC1155BTest:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 309459) -ERC1155BTest:testFailBatchMintToZero() (gas: 30941) -ERC1155BTest:testFailBurnInsufficientBalance() (gas: 7768) -ERC1155BTest:testFailMintToNonERC1155Recipient() (gas: 68217) -ERC1155BTest:testFailMintToRevertingERC1155Recipient() (gas: 259420) -ERC1155BTest:testFailMintToWrongReturnDataERC1155Recipient() (gas: 259419) -ERC1155BTest:testFailMintToZero() (gas: 13759) -ERC1155BTest:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 722319) -ERC1155BTest:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 913812) -ERC1155BTest:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 865731) -ERC1155BTest:testFailSafeBatchTransferFromToZero() (gas: 687469) -ERC1155BTest:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 674842) -ERC1155BTest:testFailSafeBatchTransferInsufficientBalance() (gas: 552088) -ERC1155BTest:testFailSafeTransferFromInsufficientBalance() (gas: 549469) -ERC1155BTest:testFailSafeTransferFromSelfInsufficientBalance() (gas: 8381) -ERC1155BTest:testFailSafeTransferFromToNonERC1155Recipient() (gas: 74192) -ERC1155BTest:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 265392) -ERC1155BTest:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 217251) -ERC1155BTest:testFailSafeTransferFromToZero() (gas: 8362) -ERC1155BTest:testMintToEOA() (gas: 34635) -ERC1155BTest:testMintToERC1155Recipient() (gas: 608188) -ERC1155BTest:testSafeBatchTransferFromToEOA() (gas: 698163) -ERC1155BTest:testSafeBatchTransferFromToERC1155Recipient() (gas: 1522381) -ERC1155BTest:testSafeTransferFromSelf() (gas: 41761) -ERC1155BTest:testSafeTransferFromToEOA() (gas: 582817) -ERC1155BTest:testSafeTransferFromToERC1155Recipient() (gas: 1175925) -ERC20Test:testApprove() (gas: 31080) -ERC20Test:testBurn() (gas: 57014) -ERC20Test:testFailPermitBadDeadline() (gas: 36924) -ERC20Test:testFailPermitBadNonce() (gas: 36874) -ERC20Test:testFailPermitPastDeadline() (gas: 10938) -ERC20Test:testFailPermitReplay() (gas: 66285) -ERC20Test:testFailTransferFromInsufficientAllowance() (gas: 80837) -ERC20Test:testFailTransferFromInsufficientBalance() (gas: 81336) -ERC20Test:testFailTransferInsufficientBalance() (gas: 52784) -ERC20Test:testInfiniteApproveTransferFrom() (gas: 89748) -ERC20Test:testMint() (gas: 53768) -ERC20Test:testPermit() (gas: 63237) -ERC20Test:testTransfer() (gas: 60228) -ERC20Test:testTransferFrom() (gas: 83821) -ERC4626Test:testFailDepositWithNoApproval() (gas: 13345) -ERC4626Test:testFailDepositWithNotEnoughApproval() (gas: 86963) -ERC4626Test:testFailDepositZero() (gas: 7790) -ERC4626Test:testFailMintWithNoApproval() (gas: 13246) -ERC4626Test:testFailRedeemWithNoShareAmount() (gas: 32333) -ERC4626Test:testFailRedeemWithNotEnoughShareAmount() (gas: 203599) -ERC4626Test:testFailRedeemZero() (gas: 7955) -ERC4626Test:testFailWithdrawWithNoUnderlyingAmount() (gas: 32286) -ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203539) -ERC4626Test:testMintZero() (gas: 54520) -ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 411122) -ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 286084) -ERC4626Test:testWithdrawZero() (gas: 52352) -ERC721Test:testApprove() (gas: 78427) -ERC721Test:testApproveAll() (gas: 31086) -ERC721Test:testApproveBurn() (gas: 65584) -ERC721Test:testBurn() (gas: 46124) -ERC721Test:testFailApproveUnAuthorized() (gas: 55598) -ERC721Test:testFailApproveUnMinted() (gas: 10194) -ERC721Test:testFailBalanceOfZeroAddress() (gas: 5576) -ERC721Test:testFailBurnUnMinted() (gas: 7857) -ERC721Test:testFailDoubleBurn() (gas: 58986) -ERC721Test:testFailDoubleMint() (gas: 53286) -ERC721Test:testFailMintToZero() (gas: 5754) -ERC721Test:testFailOwnerOfUnminted() (gas: 7631) -ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnData() (gas: 159028) -ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnDataWithData() (gas: 159825) -ERC721Test:testFailSafeMintToNonERC721Recipient() (gas: 89204) -ERC721Test:testFailSafeMintToNonERC721RecipientWithData() (gas: 89990) -ERC721Test:testFailSafeMintToRevertingERC721Recipient() (gas: 204738) -ERC721Test:testFailSafeMintToRevertingERC721RecipientWithData() (gas: 205556) -ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnData() (gas: 187272) -ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData() (gas: 187722) -ERC721Test:testFailSafeTransferFromToNonERC721Recipient() (gas: 117409) -ERC721Test:testFailSafeTransferFromToNonERC721RecipientWithData() (gas: 117889) -ERC721Test:testFailSafeTransferFromToRevertingERC721Recipient() (gas: 232982) -ERC721Test:testFailSafeTransferFromToRevertingERC721RecipientWithData() (gas: 233391) -ERC721Test:testFailTransferFromNotOwner() (gas: 57894) -ERC721Test:testFailTransferFromToZero() (gas: 53359) -ERC721Test:testFailTransferFromUnOwned() (gas: 7999) -ERC721Test:testFailTransferFromWrongFrom() (gas: 53382) -ERC721Test:testMint() (gas: 54360) -ERC721Test:testSafeMintToEOA() (gas: 56974) -ERC721Test:testSafeMintToERC721Recipient() (gas: 381730) -ERC721Test:testSafeMintToERC721RecipientWithData() (gas: 402853) -ERC721Test:testSafeTransferFromToEOA() (gas: 95627) -ERC721Test:testSafeTransferFromToERC721Recipient() (gas: 440223) -ERC721Test:testSafeTransferFromToERC721RecipientWithData() (gas: 461042) -ERC721Test:testTransferFrom() (gas: 86347) -ERC721Test:testTransferFromApproveAll() (gas: 92897) -ERC721Test:testTransferFromSelf() (gas: 64820) -FixedPointMathLibTest:testDivWadDown() (gas: 831) +AuthTest:testCallFunctionAsOwner() (gas: 29820) +AuthTest:testCallFunctionWithPermissiveAuthority() (gas: 122664) +AuthTest:testFailCallFunctionAsNonOwner() (gas: 15472) +AuthTest:testFailCallFunctionAsOwnerWithOutOfOrderAuthority() (gas: 134230) +AuthTest:testFailCallFunctionWithRestrictiveAuthority() (gas: 127567) +AuthTest:testFailFuzzCallFunctionAsNonOwner(address) (runs: 256, μ: 15635, ~: 15635) +AuthTest:testFailFuzzCallFunctionWithRestrictiveAuthority(address) (runs: 256, μ: 127708, ~: 127708) +AuthTest:testFailFuzzSetAuthorityAsNonOwner(address,address) (runs: 256, μ: 15988, ~: 15988) +AuthTest:testFailFuzzSetAuthorityWithRestrictiveAuthority(address,address) (runs: 256, μ: 127777, ~: 127777) +AuthTest:testFailFuzzSetOwnerAsNonOwner(address,address) (runs: 256, μ: 15837, ~: 15837) +AuthTest:testFailFuzzSetOwnerAsOwnerWithOutOfOrderAuthority(address) (runs: 256, μ: 134532, ~: 134532) +AuthTest:testFailFuzzSetOwnerWithRestrictiveAuthority(address,address) (runs: 256, μ: 127957, ~: 127957) +AuthTest:testFailSetAuthorityAsNonOwner() (gas: 15784) +AuthTest:testFailSetAuthorityWithRestrictiveAuthority() (gas: 127467) +AuthTest:testFailSetOwnerAsNonOwner() (gas: 15568) +AuthTest:testFailSetOwnerAsOwnerWithOutOfOrderAuthority() (gas: 134305) +AuthTest:testFailSetOwnerWithRestrictiveAuthority() (gas: 127653) +AuthTest:testFuzzCallFunctionWithPermissiveAuthority(address) (runs: 256, μ: 127612, ~: 127631) +AuthTest:testFuzzSetAuthorityAsOwner(address) (runs: 256, μ: 32417, ~: 32417) +AuthTest:testFuzzSetAuthorityWithPermissiveAuthority(address,address) (runs: 256, μ: 129427, ~: 129427) +AuthTest:testFuzzSetOwnerAsOwner(address) (runs: 256, μ: 15456, ~: 15456) +AuthTest:testFuzzSetOwnerWithPermissiveAuthority(address,address) (runs: 256, μ: 129367, ~: 129386) +AuthTest:testSetAuthorityAsOwner() (gas: 32225) +AuthTest:testSetAuthorityAsOwnerWithOutOfOrderAuthority() (gas: 223085) +AuthTest:testSetAuthorityWithPermissiveAuthority() (gas: 124311) +AuthTest:testSetOwnerAsOwner() (gas: 15263) +AuthTest:testSetOwnerWithPermissiveAuthority() (gas: 126299) +Bytes32AddressLibTest:testFillLast12Bytes() (gas: 222) +Bytes32AddressLibTest:testFromLast20Bytes() (gas: 190) +CREATE3Test:testDeployERC20() (gas: 838566) +CREATE3Test:testFailDoubleDeployDifferentBytecode() (gas: 9079256848778913899) +CREATE3Test:testFailDoubleDeploySameBytecode() (gas: 9079256848778906143) +CREATE3Test:testFailFuzzDoubleDeployDifferentBytecode(bytes32,bytes,bytes) (runs: 256, μ: 5795341072053839733, ~: 8937393460516727571) +CREATE3Test:testFailFuzzDoubleDeploySameBytecode(bytes32,bytes) (runs: 256, μ: 5725517685643553963, ~: 8937393460516728746) +CREATE3Test:testFuzzDeployERC20(bytes32,string,string,uint8) (runs: 256, μ: 884745, ~: 884757) +DSTestPlusTest:testBound() (gas: 14272) +DSTestPlusTest:testBrutalizeMemory() (gas: 817) +DSTestPlusTest:testFailBoundMinBiggerThanMax() (gas: 285) +DSTestPlusTest:testFailFuzzBoundMinBiggerThanMax(uint256,uint256,uint256) (runs: 256, μ: 500, ~: 502) +DSTestPlusTest:testFuzzBound(uint256,uint256,uint256) (runs: 256, μ: 2768, ~: 2774) +DSTestPlusTest:testMeasuringGas() (gas: 24613) +DSTestPlusTest:testRelApproxEqBothZeroesPasses() (gas: 397) +ERC1155BTest:testApproveAll() (gas: 30937) +ERC1155BTest:testBatchBalanceOf() (gas: 157123) +ERC1155BTest:testBatchBurn() (gas: 114392) +ERC1155BTest:testBatchMintToEOA() (gas: 135702) +ERC1155BTest:testBatchMintToERC1155Recipient() (gas: 981458) +ERC1155BTest:testBurn() (gas: 26484) +ERC1155BTest:testFailBalanceOfBatchWithArrayMismatch() (gas: 7917) +ERC1155BTest:testFailBatchBurnInsufficientBalance() (gas: 10036) +ERC1155BTest:testFailBatchMintToNonERC1155Recipient() (gas: 165777) +ERC1155BTest:testFailBatchMintToRevertingERC1155Recipient() (gas: 350351) +ERC1155BTest:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 304443) +ERC1155BTest:testFailBatchMintToZero() (gas: 28405) +ERC1155BTest:testFailBurnInsufficientBalance() (gas: 7760) +ERC1155BTest:testFailMintToNonERC1155Recipient() (gas: 67998) +ERC1155BTest:testFailMintToRevertingERC1155Recipient() (gas: 252217) +ERC1155BTest:testFailMintToWrongReturnDataERC1155Recipient() (gas: 252216) +ERC1155BTest:testFailMintToZero() (gas: 11246) +ERC1155BTest:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 706891) +ERC1155BTest:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 891400) +ERC1155BTest:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 845536) +ERC1155BTest:testFailSafeBatchTransferFromToZero() (gas: 669763) +ERC1155BTest:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 659674) +ERC1155BTest:testFailSafeBatchTransferInsufficientBalance() (gas: 536963) +ERC1155BTest:testFailSafeTransferFromInsufficientBalance() (gas: 534358) +ERC1155BTest:testFailSafeTransferFromSelfInsufficientBalance() (gas: 8369) +ERC1155BTest:testFailSafeTransferFromToNonERC1155Recipient() (gas: 73953) +ERC1155BTest:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 258169) +ERC1155BTest:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 212245) +ERC1155BTest:testFailSafeTransferFromToZero() (gas: 8350) +ERC1155BTest:testMintToEOA() (gas: 34620) +ERC1155BTest:testMintToERC1155Recipient() (gas: 648881) +ERC1155BTest:testSafeBatchTransferFromToEOA() (gas: 682915) +ERC1155BTest:testSafeBatchTransferFromToERC1155Recipient() (gas: 1547106) +ERC1155BTest:testSafeTransferFromSelf() (gas: 41721) +ERC1155BTest:testSafeTransferFromToEOA() (gas: 567678) +ERC1155BTest:testSafeTransferFromToERC1155Recipient() (gas: 1201505) +ERC1155Test:testApproveAll() (gas: 31043) +ERC1155Test:testBatchBalanceOf() (gas: 157479) +ERC1155Test:testBatchBurn() (gas: 150991) +ERC1155Test:testBatchMintToEOA() (gas: 137239) +ERC1155Test:testBatchMintToERC1155Recipient() (gas: 982585) +ERC1155Test:testBurn() (gas: 38560) +ERC1155Test:testFailBalanceOfBatchWithArrayMismatch() (gas: 7917) +ERC1155Test:testFailBatchBurnInsufficientBalance() (gas: 136125) +ERC1155Test:testFailBatchBurnWithArrayLengthMismatch() (gas: 135493) +ERC1155Test:testFailBatchMintToNonERC1155Recipient() (gas: 167071) +ERC1155Test:testFailBatchMintToRevertingERC1155Recipient() (gas: 351627) +ERC1155Test:testFailBatchMintToWrongReturnDataERC1155Recipient() (gas: 305726) +ERC1155Test:testFailBatchMintToZero() (gas: 129179) +ERC1155Test:testFailBatchMintWithArrayMismatch() (gas: 9599) +ERC1155Test:testFailBurnInsufficientBalance() (gas: 34813) +ERC1155Test:testFailFuzzBalanceOfBatchWithArrayMismatch(address[],uint256[]) (runs: 256, μ: 58008, ~: 58774) +ERC1155Test:testFailFuzzBatchBurnInsufficientBalance(address,uint256[],uint256[],uint256[],bytes) (runs: 256, μ: 1401703, ~: 589548) +ERC1155Test:testFailFuzzBatchBurnWithArrayLengthMismatch(address,uint256[],uint256[],uint256[],bytes) (runs: 256, μ: 86132, ~: 76405) +ERC1155Test:testFailFuzzBatchMintToNonERC1155Recipient(uint256[],uint256[],bytes) (runs: 256, μ: 3185493, ~: 2668585) +ERC1155Test:testFailFuzzBatchMintToRevertingERC1155Recipient(uint256[],uint256[],bytes) (runs: 256, μ: 3370046, ~: 2853136) +ERC1155Test:testFailFuzzBatchMintToWrongReturnDataERC1155Recipient(uint256[],uint256[],bytes) (runs: 256, μ: 3324166, ~: 2807257) +ERC1155Test:testFailFuzzBatchMintToZero(uint256[],uint256[],bytes) (runs: 256, μ: 3123488, ~: 2605508) +ERC1155Test:testFailFuzzBatchMintWithArrayMismatch(address,uint256[],uint256[],bytes) (runs: 256, μ: 66403, ~: 66465) +ERC1155Test:testFailFuzzBurnInsufficientBalance(address,uint256,uint256,uint256,bytes) (runs: 256, μ: 35147, ~: 38181) +ERC1155Test:testFailFuzzMintToNonERC155Recipient(uint256,uint256,bytes) (runs: 256, μ: 68208, ~: 68890) +ERC1155Test:testFailFuzzMintToRevertingERC155Recipient(uint256,uint256,bytes) (runs: 256, μ: 252441, ~: 253123) +ERC1155Test:testFailFuzzMintToWrongReturnDataERC155Recipient(uint256,uint256,bytes) (runs: 256, μ: 252463, ~: 253145) +ERC1155Test:testFailFuzzMintToZero(uint256,uint256,bytes) (runs: 256, μ: 31314, ~: 32044) +ERC1155Test:testFailFuzzSafeBatchTransferFromToNonERC1155Recipient(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 3541335, ~: 2961230) +ERC1155Test:testFailFuzzSafeBatchTransferFromToRevertingERC1155Recipient(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 3725895, ~: 3145784) +ERC1155Test:testFailFuzzSafeBatchTransferFromToWrongReturnDataERC1155Recipient(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 3680014, ~: 3099906) +ERC1155Test:testFailFuzzSafeBatchTransferFromToZero(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 3503972, ~: 2923813) +ERC1155Test:testFailFuzzSafeBatchTransferFromWithArrayLengthMismatch(address,uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 79071, ~: 76639) +ERC1155Test:testFailFuzzSafeBatchTransferInsufficientBalance(address,uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 1805127, ~: 647144) +ERC1155Test:testFailFuzzSafeTransferFromInsufficientBalance(address,uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 62851, ~: 67305) +ERC1155Test:testFailFuzzSafeTransferFromSelfInsufficientBalance(address,uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 35616, ~: 38441) +ERC1155Test:testFailFuzzSafeTransferFromToNonERC155Recipient(uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 96370, ~: 100283) +ERC1155Test:testFailFuzzSafeTransferFromToRevertingERC1155Recipient(uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 280577, ~: 284490) +ERC1155Test:testFailFuzzSafeTransferFromToWrongReturnDataERC1155Recipient(uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 234638, ~: 238551) +ERC1155Test:testFailFuzzSafeTransferFromToZero(uint256,uint256,uint256,bytes,bytes) (runs: 256, μ: 59557, ~: 63473) +ERC1155Test:testFailMintToNonERC155Recipient() (gas: 67978) +ERC1155Test:testFailMintToRevertingERC155Recipient() (gas: 252215) +ERC1155Test:testFailMintToWrongReturnDataERC155Recipient() (gas: 252214) +ERC1155Test:testFailMintToZero() (gas: 31190) +ERC1155Test:testFailSafeBatchTransferFromToNonERC1155Recipient() (gas: 321099) +ERC1155Test:testFailSafeBatchTransferFromToRevertingERC1155Recipient() (gas: 505691) +ERC1155Test:testFailSafeBatchTransferFromToWrongReturnDataERC1155Recipient() (gas: 459830) +ERC1155Test:testFailSafeBatchTransferFromToZero() (gas: 283994) +ERC1155Test:testFailSafeBatchTransferFromWithArrayLengthMismatch() (gas: 162592) +ERC1155Test:testFailSafeBatchTransferInsufficientBalance() (gas: 163472) +ERC1155Test:testFailSafeTransferFromInsufficientBalance() (gas: 63239) +ERC1155Test:testFailSafeTransferFromSelfInsufficientBalance() (gas: 34297) +ERC1155Test:testFailSafeTransferFromToNonERC155Recipient() (gas: 96289) +ERC1155Test:testFailSafeTransferFromToRevertingERC1155Recipient() (gas: 280527) +ERC1155Test:testFailSafeTransferFromToWrongReturnDataERC1155Recipient() (gas: 234610) +ERC1155Test:testFailSafeTransferFromToZero() (gas: 59492) +ERC1155Test:testFuzzApproveAll(address,bool) (runs: 256, μ: 22805, ~: 31343) +ERC1155Test:testFuzzBatchBalanceOf(address[],uint256[],uint256[],bytes) (runs: 256, μ: 3542457, ~: 2926682) +ERC1155Test:testFuzzBatchBurn(address,uint256[],uint256[],uint256[],bytes) (runs: 256, μ: 3623036, ~: 3043733) +ERC1155Test:testFuzzBatchMintToEOA(address,uint256[],uint256[],bytes) (runs: 256, μ: 3056089, ~: 2515633) +ERC1155Test:testFuzzBatchMintToERC1155Recipient(uint256[],uint256[],bytes) (runs: 256, μ: 7362382, ~: 6420706) +ERC1155Test:testFuzzBurn(address,uint256,uint256,bytes,uint256) (runs: 256, μ: 40402, ~: 42070) +ERC1155Test:testFuzzMintToEOA(address,uint256,uint256,bytes) (runs: 256, μ: 35331, ~: 35837) +ERC1155Test:testFuzzMintToERC1155Recipient(uint256,uint256,bytes) (runs: 256, μ: 678703, ~: 672019) +ERC1155Test:testFuzzSafeBatchTransferFromToEOA(address,uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 5007136, ~: 4004697) +ERC1155Test:testFuzzSafeBatchTransferFromToERC1155Recipient(uint256[],uint256[],uint256[],bytes,bytes) (runs: 256, μ: 7737773, ~: 6601105) +ERC1155Test:testFuzzSafeTransferFromSelf(uint256,uint256,bytes,uint256,address,bytes) (runs: 256, μ: 64147, ~: 68471) +ERC1155Test:testFuzzSafeTransferFromToEOA(uint256,uint256,bytes,uint256,address,bytes) (runs: 256, μ: 93877, ~: 97364) +ERC1155Test:testFuzzSafeTransferFromToERC1155Recipient(uint256,uint256,bytes,uint256,bytes) (runs: 256, μ: 757169, ~: 753330) +ERC1155Test:testMintToEOA() (gas: 34726) +ERC1155Test:testMintToERC1155Recipient() (gas: 649024) +ERC1155Test:testSafeBatchTransferFromToEOA() (gas: 297744) +ERC1155Test:testSafeBatchTransferFromToERC1155Recipient() (gas: 1162187) +ERC1155Test:testSafeTransferFromSelf() (gas: 64127) +ERC1155Test:testSafeTransferFromToEOA() (gas: 93135) +ERC1155Test:testSafeTransferFromToERC1155Recipient() (gas: 727206) +ERC20Invariants:invariantBalanceSum() (runs: 256, calls: 3840, reverts: 2336) +ERC20Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2603) +ERC20Test:testApprove() (gas: 31071) +ERC20Test:testBurn() (gas: 57007) +ERC20Test:testFailFuzzBurnInsufficientBalance(address,uint256,uint256) (runs: 256, μ: 52049, ~: 55453) +ERC20Test:testFailFuzzPermitBadDeadline(uint256,address,uint256,uint256) (runs: 256, μ: 31762, ~: 37146) +ERC20Test:testFailFuzzPermitBadNonce(uint256,address,uint256,uint256,uint256) (runs: 256, μ: 32109, ~: 37135) +ERC20Test:testFailFuzzPermitPastDeadline(uint256,address,uint256,uint256) (runs: 256, μ: 11956, ~: 13140) +ERC20Test:testFailFuzzPermitReplay(uint256,address,uint256,uint256) (runs: 256, μ: 55887, ~: 66560) +ERC20Test:testFailFuzzTransferFromInsufficientAllowance(address,uint256,uint256) (runs: 256, μ: 79520, ~: 83392) +ERC20Test:testFailFuzzTransferFromInsufficientBalance(address,uint256,uint256) (runs: 256, μ: 79395, ~: 83943) +ERC20Test:testFailFuzzTransferInsufficientBalance(address,uint256,uint256) (runs: 256, μ: 51940, ~: 55338) +ERC20Test:testFailPermitBadDeadline() (gas: 36901) +ERC20Test:testFailPermitBadNonce() (gas: 36847) +ERC20Test:testFailPermitPastDeadline() (gas: 10930) +ERC20Test:testFailPermitReplay() (gas: 66245) +ERC20Test:testFailTransferFromInsufficientAllowance() (gas: 80826) +ERC20Test:testFailTransferFromInsufficientBalance() (gas: 81331) +ERC20Test:testFailTransferInsufficientBalance() (gas: 52780) +ERC20Test:testFuzzApprove(address,uint256) (runs: 256, μ: 29905, ~: 31227) +ERC20Test:testFuzzBurn(address,uint256,uint256) (runs: 256, μ: 57908, ~: 59679) +ERC20Test:testFuzzMetadata(string,string,uint8) (runs: 256, μ: 832653, ~: 826936) +ERC20Test:testFuzzMint(address,uint256) (runs: 256, μ: 51428, ~: 53916) +ERC20Test:testFuzzPermit(uint248,address,uint256,uint256) (runs: 256, μ: 62467, ~: 63478) +ERC20Test:testFuzzTransfer(address,uint256) (runs: 256, μ: 57942, ~: 60430) +ERC20Test:testFuzzTransferFrom(address,uint256,uint256) (runs: 256, μ: 86993, ~: 92814) +ERC20Test:testInfiniteApproveTransferFrom() (gas: 89725) +ERC20Test:testMint() (gas: 53759) +ERC20Test:testPermit() (gas: 63202) +ERC20Test:testTransfer() (gas: 60218) +ERC20Test:testTransferFrom() (gas: 83808) +ERC4626Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2920) +ERC4626Test:testFailDepositWithNoApproval() (gas: 13335) +ERC4626Test:testFailDepositWithNotEnoughApproval() (gas: 86944) +ERC4626Test:testFailDepositZero() (gas: 7785) +ERC4626Test:testFailMintWithNoApproval() (gas: 13232) +ERC4626Test:testFailRedeemWithNoShareAmount() (gas: 32326) +ERC4626Test:testFailRedeemWithNotEnoughShareAmount() (gas: 203581) +ERC4626Test:testFailRedeemZero() (gas: 7949) +ERC4626Test:testFailWithdrawWithNoUnderlyingAmount() (gas: 32275) +ERC4626Test:testFailWithdrawWithNotEnoughUnderlyingAmount() (gas: 203517) +ERC4626Test:testFuzzMetadata(string,string) (runs: 256, μ: 1426162, ~: 1426681) +ERC4626Test:testFuzzSingleDepositWithdraw(uint128) (runs: 256, μ: 201323, ~: 201334) +ERC4626Test:testFuzzSingleMintRedeem(uint128) (runs: 256, μ: 201291, ~: 201302) +ERC4626Test:testMintZero() (gas: 54488) +ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 410676) +ERC4626Test:testVaultInteractionsForSomeoneElse() (gas: 285997) +ERC4626Test:testWithdrawZero() (gas: 52318) +ERC721Test:invariantMetadata() (runs: 256, calls: 3840, reverts: 2181) +ERC721Test:testApprove() (gas: 78410) +ERC721Test:testApproveAll() (gas: 31076) +ERC721Test:testApproveBurn() (gas: 65556) +ERC721Test:testBurn() (gas: 46104) +ERC721Test:testFailApproveUnAuthorized() (gas: 55583) +ERC721Test:testFailApproveUnMinted() (gas: 10185) +ERC721Test:testFailBalanceOfZeroAddress() (gas: 5569) +ERC721Test:testFailBurnUnMinted() (gas: 7849) +ERC721Test:testFailDoubleBurn() (gas: 58966) +ERC721Test:testFailDoubleMint() (gas: 53272) +ERC721Test:testFailFuzzApproveUnAuthorized(address,uint256,address) (runs: 256, μ: 55908, ~: 55909) +ERC721Test:testFailFuzzApproveUnMinted(uint256,address) (runs: 256, μ: 10363, ~: 10363) +ERC721Test:testFailFuzzBurnUnMinted(uint256) (runs: 256, μ: 7895, ~: 7895) +ERC721Test:testFailFuzzDoubleBurn(uint256,address) (runs: 256, μ: 59143, ~: 59143) +ERC721Test:testFailFuzzDoubleMint(uint256,address) (runs: 256, μ: 53481, ~: 53481) +ERC721Test:testFailFuzzMintToZero(uint256) (runs: 256, μ: 5802, ~: 5802) +ERC721Test:testFailFuzzOwnerOfUnminted(uint256) (runs: 256, μ: 7704, ~: 7704) +ERC721Test:testFailFuzzSafeMintToERC721RecipientWithWrongReturnData(uint256) (runs: 256, μ: 156725, ~: 156725) +ERC721Test:testFailFuzzSafeMintToERC721RecipientWithWrongReturnDataWithData(uint256,bytes) (runs: 256, μ: 157825, ~: 157770) +ERC721Test:testFailFuzzSafeMintToNonERC721Recipient(uint256) (runs: 256, μ: 89049, ~: 89049) +ERC721Test:testFailFuzzSafeMintToNonERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 90178, ~: 90122) +ERC721Test:testFailFuzzSafeMintToRevertingERC721Recipient(uint256) (runs: 256, μ: 200418, ~: 200418) +ERC721Test:testFailFuzzSafeMintToRevertingERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 201515, ~: 201460) +ERC721Test:testFailFuzzSafeTransferFromToERC721RecipientWithWrongReturnData(uint256) (runs: 256, μ: 184922, ~: 184922) +ERC721Test:testFailFuzzSafeTransferFromToERC721RecipientWithWrongReturnDataWithData(uint256,bytes) (runs: 256, μ: 185648, ~: 185644) +ERC721Test:testFailFuzzSafeTransferFromToNonERC721Recipient(uint256) (runs: 256, μ: 117293, ~: 117293) +ERC721Test:testFailFuzzSafeTransferFromToNonERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 118007, ~: 118003) +ERC721Test:testFailFuzzSafeTransferFromToRevertingERC721Recipient(uint256) (runs: 256, μ: 228660, ~: 228660) +ERC721Test:testFailFuzzSafeTransferFromToRevertingERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 229362, ~: 229358) +ERC721Test:testFailFuzzTransferFromNotOwner(address,address,uint256) (runs: 256, μ: 57575, ~: 58187) +ERC721Test:testFailFuzzTransferFromToZero(uint256) (runs: 256, μ: 53446, ~: 53446) +ERC721Test:testFailFuzzTransferFromUnOwned(address,address,uint256) (runs: 256, μ: 8264, ~: 8229) +ERC721Test:testFailFuzzTransferFromWrongFrom(address,address,address,uint256) (runs: 256, μ: 53156, ~: 53714) +ERC721Test:testFailMintToZero() (gas: 5746) +ERC721Test:testFailOwnerOfUnminted() (gas: 7625) +ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnData() (gas: 156627) +ERC721Test:testFailSafeMintToERC721RecipientWithWrongReturnDataWithData() (gas: 157395) +ERC721Test:testFailSafeMintToNonERC721Recipient() (gas: 88991) +ERC721Test:testFailSafeMintToNonERC721RecipientWithData() (gas: 89748) +ERC721Test:testFailSafeMintToRevertingERC721Recipient() (gas: 200318) +ERC721Test:testFailSafeMintToRevertingERC721RecipientWithData() (gas: 201107) +ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnData() (gas: 184864) +ERC721Test:testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData() (gas: 185311) +ERC721Test:testFailSafeTransferFromToNonERC721Recipient() (gas: 117189) +ERC721Test:testFailSafeTransferFromToNonERC721RecipientWithData() (gas: 117666) +ERC721Test:testFailSafeTransferFromToRevertingERC721Recipient() (gas: 228555) +ERC721Test:testFailSafeTransferFromToRevertingERC721RecipientWithData() (gas: 228961) +ERC721Test:testFailTransferFromNotOwner() (gas: 57877) +ERC721Test:testFailTransferFromToZero() (gas: 53343) +ERC721Test:testFailTransferFromUnOwned() (gas: 7990) +ERC721Test:testFailTransferFromWrongFrom() (gas: 53367) +ERC721Test:testFuzzApprove(address,uint256) (runs: 256, μ: 78622, ~: 78622) +ERC721Test:testFuzzApproveAll(address,bool) (runs: 256, μ: 22838, ~: 31376) +ERC721Test:testFuzzApproveBurn(address,uint256) (runs: 256, μ: 65422, ~: 65556) +ERC721Test:testFuzzBurn(address,uint256) (runs: 256, μ: 46145, ~: 46158) +ERC721Test:testFuzzMetadata(string,string) (runs: 256, μ: 1288827, ~: 1289171) +ERC721Test:testFuzzMint(address,uint256) (runs: 256, μ: 54515, ~: 54515) +ERC721Test:testFuzzSafeMintToEOA(uint256,address) (runs: 256, μ: 57119, ~: 57342) +ERC721Test:testFuzzSafeMintToERC721Recipient(uint256) (runs: 256, μ: 418437, ~: 419526) +ERC721Test:testFuzzSafeMintToERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 472331, ~: 463252) +ERC721Test:testFuzzSafeTransferFromToEOA(uint256,address) (runs: 256, μ: 95257, ~: 96003) +ERC721Test:testFuzzSafeTransferFromToERC721Recipient(uint256) (runs: 256, μ: 476974, ~: 478063) +ERC721Test:testFuzzSafeTransferFromToERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 530499, ~: 521472) +ERC721Test:testFuzzTransferFrom(uint256,address) (runs: 256, μ: 86434, ~: 86446) +ERC721Test:testFuzzTransferFromApproveAll(uint256,address) (runs: 256, μ: 93171, ~: 93171) +ERC721Test:testFuzzTransferFromSelf(uint256,address) (runs: 256, μ: 65049, ~: 65050) +ERC721Test:testMint() (gas: 54344) +ERC721Test:testSafeMintToEOA() (gas: 56958) +ERC721Test:testSafeMintToERC721Recipient() (gas: 419441) +ERC721Test:testSafeMintToERC721RecipientWithData() (gas: 440475) +ERC721Test:testSafeTransferFromToEOA() (gas: 95585) +ERC721Test:testSafeTransferFromToERC721Recipient() (gas: 477909) +ERC721Test:testSafeTransferFromToERC721RecipientWithData() (gas: 498665) +ERC721Test:testTransferFrom() (gas: 86312) +ERC721Test:testTransferFromApproveAll() (gas: 92855) +ERC721Test:testTransferFromSelf() (gas: 64786) +FixedPointMathLibTest:testDivWadDown() (gas: 838) FixedPointMathLibTest:testDivWadDownEdgeCases() (gas: 435) -FixedPointMathLibTest:testDivWadUp() (gas: 949) +FixedPointMathLibTest:testDivWadUp() (gas: 957) FixedPointMathLibTest:testDivWadUpEdgeCases() (gas: 450) -FixedPointMathLibTest:testExpWad() (gas: 7303) -FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 330) -FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 309) -FixedPointMathLibTest:testFailMulDivDownZeroDenominator() (gas: 338) -FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 296) -FixedPointMathLibTest:testFuzzLog2() (gas: 315757) -FixedPointMathLibTest:testLnWad() (gas: 2416) -FixedPointMathLibTest:testLnWadBig() (gas: 2392) -FixedPointMathLibTest:testLnWadNegative() (gas: 232) -FixedPointMathLibTest:testLnWadOverflow() (gas: 209) -FixedPointMathLibTest:testLnWadSmall() (gas: 3142) -FixedPointMathLibTest:testLog2() (gas: 1755) -FixedPointMathLibTest:testMulDivDown() (gas: 1883) -FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 729) -FixedPointMathLibTest:testMulDivUp() (gas: 2250) -FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 846) -FixedPointMathLibTest:testMulWadDown() (gas: 844) -FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 887) -FixedPointMathLibTest:testMulWadUp() (gas: 1003) -FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 981) -FixedPointMathLibTest:testRPow() (gas: 2142) -FixedPointMathLibTest:testSqrt() (gas: 2091) -LibBitmapTest:testBitmapGet() (gas: 7806) -LibBitmapTest:testBitmapSet() (gas: 28649) -LibBitmapTest:testBitmapSetTo() (gas: 20672) -MerkleProofTest:testValidProofSupplied() (gas: 2217) -MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 1498) -MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 1492) -MerkleProofTest:testVerifyInvalidProofSupplied() (gas: 2236) -MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34293) -MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80575) -MultiRolesAuthorityTest:testCanCallWithCustomAuthority() (gas: 422681) -MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesPublicCapability() (gas: 247696) -MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesUserWithRole() (gas: 256828) -MultiRolesAuthorityTest:testSetPublicCapabilities() (gas: 27762) -MultiRolesAuthorityTest:testSetRoleCapabilities() (gas: 28968) -MultiRolesAuthorityTest:testSetRoles() (gas: 28971) -MultiRolesAuthorityTest:testSetTargetCustomAuthority() (gas: 27976) -OwnedTest:testCallFunctionAsNonOwner() (gas: 11311) -OwnedTest:testCallFunctionAsOwner() (gas: 10479) -OwnedTest:testSetOwner() (gas: 13035) -ReentrancyGuardTest:testFailUnprotectedCall() (gas: 46167) -ReentrancyGuardTest:testNoReentrancy() (gas: 7515) -ReentrancyGuardTest:testProtectedCall() (gas: 33470) -RolesAuthorityTest:testCanCallPublicCapability() (gas: 33319) -RolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 79584) -RolesAuthorityTest:testSetPublicCapabilities() (gas: 29183) -RolesAuthorityTest:testSetRoleCapabilities() (gas: 30276) -RolesAuthorityTest:testSetRoles() (gas: 28951) -SSTORE2Test:testFailReadInvalidPointer() (gas: 2905) -SSTORE2Test:testFailReadInvalidPointerCustomBounds() (gas: 3098) -SSTORE2Test:testFailReadInvalidPointerCustomStartBound() (gas: 3004) -SSTORE2Test:testFailWriteReadEmptyOutOfBounds() (gas: 34448) -SSTORE2Test:testFailWriteReadOutOfBounds() (gas: 34426) -SSTORE2Test:testFailWriteReadOutOfStartBound() (gas: 34317) -SSTORE2Test:testWriteRead() (gas: 53497) -SSTORE2Test:testWriteReadCustomBounds() (gas: 34869) -SSTORE2Test:testWriteReadCustomStartBound() (gas: 34784) -SSTORE2Test:testWriteReadEmptyBound() (gas: 34677) -SSTORE2Test:testWriteReadFullBoundedRead() (gas: 53716) -SSTORE2Test:testWriteReadFullStartBound() (gas: 34764) -SafeCastLibTest:testFailSafeCastTo128() (gas: 364) -SafeCastLibTest:testFailSafeCastTo160() (gas: 320) -SafeCastLibTest:testFailSafeCastTo192() (gas: 344) -SafeCastLibTest:testFailSafeCastTo224() (gas: 320) -SafeCastLibTest:testFailSafeCastTo248() (gas: 343) -SafeCastLibTest:testFailSafeCastTo32() (gas: 319) -SafeCastLibTest:testFailSafeCastTo64() (gas: 364) -SafeCastLibTest:testFailSafeCastTo8() (gas: 339) -SafeCastLibTest:testFailSafeCastTo96() (gas: 365) -SafeCastLibTest:testSafeCastTo128() (gas: 471) -SafeCastLibTest:testSafeCastTo160() (gas: 469) -SafeCastLibTest:testSafeCastTo192() (gas: 471) -SafeCastLibTest:testSafeCastTo224() (gas: 470) -SafeCastLibTest:testSafeCastTo248() (gas: 449) -SafeCastLibTest:testSafeCastTo32() (gas: 493) -SafeCastLibTest:testSafeCastTo64() (gas: 448) -SafeCastLibTest:testSafeCastTo8() (gas: 468) -SafeCastLibTest:testSafeCastTo96() (gas: 448) -SafeTransferLibTest:testApproveWithMissingReturn() (gas: 30759) -SafeTransferLibTest:testApproveWithNonContract() (gas: 3032) -SafeTransferLibTest:testApproveWithReturnsTooMuch() (gas: 31117) -SafeTransferLibTest:testApproveWithStandardERC20() (gas: 30845) -SafeTransferLibTest:testFailApproveWithReturnsFalse() (gas: 5610) -SafeTransferLibTest:testFailApproveWithReturnsTooLittle() (gas: 5553) -SafeTransferLibTest:testFailApproveWithReverting() (gas: 5575) -SafeTransferLibTest:testFailTransferETHToContractWithoutFallback() (gas: 7266) -SafeTransferLibTest:testFailTransferFromWithReturnsFalse() (gas: 13640) -SafeTransferLibTest:testFailTransferFromWithReturnsTooLittle() (gas: 13545) -SafeTransferLibTest:testFailTransferFromWithReverting() (gas: 9779) -SafeTransferLibTest:testFailTransferWithReturnsFalse() (gas: 8560) -SafeTransferLibTest:testFailTransferWithReturnsTooLittle() (gas: 8479) -SafeTransferLibTest:testFailTransferWithReverting() (gas: 8500) -SafeTransferLibTest:testTransferETH() (gas: 34636) -SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 49200) -SafeTransferLibTest:testTransferFromWithNonContract() (gas: 3002) -SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 49825) -SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 47618) -SafeTransferLibTest:testTransferWithMissingReturn() (gas: 36671) -SafeTransferLibTest:testTransferWithNonContract() (gas: 3053) -SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 37074) -SafeTransferLibTest:testTransferWithStandardERC20() (gas: 36745) -WETHTest:testDeposit() (gas: 63238) -WETHTest:testFallbackDeposit() (gas: 63546) -WETHTest:testPartialWithdraw() (gas: 73259) -WETHTest:testWithdraw() (gas: 54360) +FixedPointMathLibTest:testExpWad() (gas: 7268) +FixedPointMathLibTest:testFailDivWadDownZeroDenominator() (gas: 326) +FixedPointMathLibTest:testFailDivWadUpZeroDenominator() (gas: 305) +FixedPointMathLibTest:testFailFuzzDivWadDownOverflow(uint256,uint256) (runs: 256, μ: 439, ~: 416) +FixedPointMathLibTest:testFailFuzzDivWadDownZeroDenominator(uint256) (runs: 256, μ: 401, ~: 401) +FixedPointMathLibTest:testFailFuzzDivWadUpOverflow(uint256,uint256) (runs: 256, μ: 394, ~: 371) +FixedPointMathLibTest:testFailFuzzDivWadUpZeroDenominator(uint256) (runs: 256, μ: 423, ~: 423) +FixedPointMathLibTest:testFailFuzzMulDivDownOverflow(uint256,uint256,uint256) (runs: 256, μ: 481, ~: 455) +FixedPointMathLibTest:testFailFuzzMulDivDownZeroDenominator(uint256,uint256) (runs: 256, μ: 392, ~: 392) +FixedPointMathLibTest:testFailFuzzMulDivUpOverflow(uint256,uint256,uint256) (runs: 256, μ: 437, ~: 411) +FixedPointMathLibTest:testFailFuzzMulDivUpZeroDenominator(uint256,uint256) (runs: 256, μ: 435, ~: 435) +FixedPointMathLibTest:testFailFuzzMulWadDownOverflow(uint256,uint256) (runs: 256, μ: 401, ~: 362) +FixedPointMathLibTest:testFailFuzzMulWadUpOverflow(uint256,uint256) (runs: 256, μ: 443, ~: 404) +FixedPointMathLibTest:testFailMulDivDownZeroDenominator() (gas: 335) +FixedPointMathLibTest:testFailMulDivUpZeroDenominator() (gas: 293) +FixedPointMathLibTest:testFuzzDivWadDown(uint256,uint256) (runs: 256, μ: 655, ~: 765) +FixedPointMathLibTest:testFuzzDivWadUp(uint256,uint256) (runs: 256, μ: 795, ~: 976) +FixedPointMathLibTest:testFuzzLog2() (gas: 302294) +FixedPointMathLibTest:testFuzzMulDivDown(uint256,uint256,uint256) (runs: 256, μ: 680, ~: 791) +FixedPointMathLibTest:testFuzzMulDivUp(uint256,uint256,uint256) (runs: 256, μ: 851, ~: 1092) +FixedPointMathLibTest:testFuzzMulWadDown(uint256,uint256) (runs: 256, μ: 682, ~: 814) +FixedPointMathLibTest:testFuzzMulWadUp(uint256,uint256) (runs: 256, μ: 808, ~: 1069) +FixedPointMathLibTest:testFuzzSqrt(uint256) (runs: 256, μ: 1020, ~: 1038) +FixedPointMathLibTest:testLnWad() (gas: 2405) +FixedPointMathLibTest:testLnWadBig() (gas: 2382) +FixedPointMathLibTest:testLnWadNegative() (gas: 231) +FixedPointMathLibTest:testLnWadOverflow() (gas: 208) +FixedPointMathLibTest:testLnWadSmall() (gas: 3129) +FixedPointMathLibTest:testLog2() (gas: 1749) +FixedPointMathLibTest:testMulDivDown() (gas: 1882) +FixedPointMathLibTest:testMulDivDownEdgeCases() (gas: 722) +FixedPointMathLibTest:testMulDivUp() (gas: 2249) +FixedPointMathLibTest:testMulDivUpEdgeCases() (gas: 839) +FixedPointMathLibTest:testMulWadDown() (gas: 851) +FixedPointMathLibTest:testMulWadDownEdgeCases() (gas: 889) +FixedPointMathLibTest:testMulWadUp() (gas: 1011) +FixedPointMathLibTest:testMulWadUpEdgeCases() (gas: 983) +FixedPointMathLibTest:testRPow() (gas: 2137) +FixedPointMathLibTest:testSqrt() (gas: 2088) +LibBitmapTest:testBitmapGet() (gas: 7801) +LibBitmapTest:testBitmapGet(uint256) (runs: 256, μ: 7827, ~: 7827) +LibBitmapTest:testBitmapSet() (gas: 28639) +LibBitmapTest:testBitmapSet(uint256) (runs: 256, μ: 28667, ~: 28667) +LibBitmapTest:testBitmapSetTo() (gas: 20656) +LibBitmapTest:testBitmapSetTo(uint256,bool) (runs: 256, μ: 21097, ~: 28949) +MerkleProofTest:testValidProofSupplied() (gas: 2201) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() (gas: 1486) +MerkleProofTest:testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() (gas: 1481) +MerkleProofTest:testVerifyInvalidProofSupplied() (gas: 2219) +MultiRolesAuthorityTest:testCanCallPublicCapability() (gas: 34263) +MultiRolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 80500) +MultiRolesAuthorityTest:testCanCallWithCustomAuthority() (gas: 416279) +MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesPublicCapability() (gas: 244437) +MultiRolesAuthorityTest:testCanCallWithCustomAuthorityOverridesUserWithRole() (gas: 254174) +MultiRolesAuthorityTest:testFuzzCanCallPublicCapability(address,address,bytes4) (runs: 256, μ: 34410, ~: 34381) +MultiRolesAuthorityTest:testFuzzCanCallWithAuthorizedRole(address,uint8,address,bytes4) (runs: 256, μ: 80749, ~: 80720) +MultiRolesAuthorityTest:testFuzzCanCallWithCustomAuthority(address,address,bytes4) (runs: 256, μ: 416750, ~: 416750) +MultiRolesAuthorityTest:testFuzzCanCallWithCustomAuthorityOverridesPublicCapability(address,address,bytes4) (runs: 256, μ: 244898, ~: 244898) +MultiRolesAuthorityTest:testFuzzCanCallWithCustomAuthorityOverridesUserWithRole(address,uint8,address,bytes4) (runs: 256, μ: 254507, ~: 254480) +MultiRolesAuthorityTest:testFuzzSetPublicCapabilities(bytes4) (runs: 256, μ: 27849, ~: 27846) +MultiRolesAuthorityTest:testFuzzSetRoleCapabilities(uint8,bytes4) (runs: 256, μ: 29119, ~: 29116) +MultiRolesAuthorityTest:testFuzzSetRoles(address,uint8) (runs: 256, μ: 29106, ~: 29092) +MultiRolesAuthorityTest:testFuzzSetTargetCustomAuthority(address,address) (runs: 256, μ: 27992, ~: 27992) +MultiRolesAuthorityTest:testSetPublicCapabilities() (gas: 27738) +MultiRolesAuthorityTest:testSetRoleCapabilities() (gas: 28939) +MultiRolesAuthorityTest:testSetRoles() (gas: 28942) +MultiRolesAuthorityTest:testSetTargetCustomAuthority() (gas: 27951) +OwnedTest:testCallFunctionAsNonOwner() (gas: 11294) +OwnedTest:testCallFunctionAsNonOwner(address) (runs: 256, μ: 16165, ~: 16240) +OwnedTest:testCallFunctionAsOwner() (gas: 10472) +OwnedTest:testSetOwner() (gas: 13024) +OwnedTest:testSetOwner(address) (runs: 256, μ: 13083, ~: 13158) +ReentrancyGuardTest:invariantReentrancyStatusAlways1() (runs: 256, calls: 3840, reverts: 280) +ReentrancyGuardTest:testFailUnprotectedCall() (gas: 46076) +ReentrancyGuardTest:testNoReentrancy() (gas: 7508) +ReentrancyGuardTest:testProtectedCall() (gas: 33453) +RolesAuthorityTest:testCanCallPublicCapability() (gas: 33289) +RolesAuthorityTest:testCanCallWithAuthorizedRole() (gas: 79514) +RolesAuthorityTest:testFuzzCanCallPublicCapability(address,address,bytes4) (runs: 256, μ: 33472, ~: 33445) +RolesAuthorityTest:testFuzzCanCallWithAuthorizedRole(address,uint8,address,bytes4) (runs: 256, μ: 79802, ~: 79775) +RolesAuthorityTest:testFuzzSetPublicCapabilities(address,bytes4) (runs: 256, μ: 29289, ~: 29271) +RolesAuthorityTest:testFuzzSetRoleCapabilities(uint8,address,bytes4) (runs: 256, μ: 30442, ~: 30425) +RolesAuthorityTest:testFuzzSetRoles(address,uint8) (runs: 256, μ: 29127, ~: 29113) +RolesAuthorityTest:testSetPublicCapabilities() (gas: 29157) +RolesAuthorityTest:testSetRoleCapabilities() (gas: 30244) +RolesAuthorityTest:testSetRoles() (gas: 28922) +SSTORE2Test:testFailFuzzReadInvalidPointer(address,bytes) (runs: 256, μ: 3828, ~: 3891) +SSTORE2Test:testFailFuzzReadInvalidPointerCustomBounds(address,uint256,uint256,bytes) (runs: 256, μ: 4090, ~: 4157) +SSTORE2Test:testFailFuzzReadInvalidPointerCustomStartBound(address,uint256,bytes) (runs: 256, μ: 3952, ~: 3990) +SSTORE2Test:testFailFuzzWriteReadCustomBoundsOutOfRange(bytes,uint256,uint256,bytes) (runs: 256, μ: 46187, ~: 43562) +SSTORE2Test:testFailFuzzWriteReadCustomStartBoundOutOfRange(bytes,uint256,bytes) (runs: 256, μ: 45965, ~: 43407) +SSTORE2Test:testFailReadInvalidPointer() (gas: 2908) +SSTORE2Test:testFailReadInvalidPointerCustomBounds() (gas: 3107) +SSTORE2Test:testFailReadInvalidPointerCustomStartBound() (gas: 3012) +SSTORE2Test:testFailWriteReadEmptyOutOfBounds() (gas: 34383) +SSTORE2Test:testFailWriteReadOutOfBounds() (gas: 34361) +SSTORE2Test:testFailWriteReadOutOfStartBound() (gas: 34251) +SSTORE2Test:testFuzzWriteRead(bytes,bytes) (runs: 256, μ: 43912, ~: 41456) +SSTORE2Test:testFuzzWriteReadCustomBounds(bytes,uint256,uint256,bytes) (runs: 256, μ: 26881, ~: 5896) +SSTORE2Test:testFuzzWriteReadCustomStartBound(bytes,uint256,bytes) (runs: 256, μ: 46451, ~: 44027) +SSTORE2Test:testWriteRead() (gas: 53449) +SSTORE2Test:testWriteReadCustomBounds() (gas: 34812) +SSTORE2Test:testWriteReadCustomStartBound() (gas: 34722) +SSTORE2Test:testWriteReadEmptyBound() (gas: 34620) +SSTORE2Test:testWriteReadFullBoundedRead() (gas: 53678) +SSTORE2Test:testWriteReadFullStartBound() (gas: 34701) +SafeCastLibTest:testFailFuzzSafeCastTo128(uint256) (runs: 256, μ: 372, ~: 372) +SafeCastLibTest:testFailFuzzSafeCastTo160(uint256) (runs: 256, μ: 416, ~: 416) +SafeCastLibTest:testFailFuzzSafeCastTo192(uint256) (runs: 256, μ: 395, ~: 395) +SafeCastLibTest:testFailFuzzSafeCastTo224(uint256) (runs: 256, μ: 394, ~: 394) +SafeCastLibTest:testFailFuzzSafeCastTo248(uint256) (runs: 256, μ: 438, ~: 438) +SafeCastLibTest:testFailFuzzSafeCastTo32(uint256) (runs: 256, μ: 395, ~: 395) +SafeCastLibTest:testFailFuzzSafeCastTo64(uint256) (runs: 256, μ: 373, ~: 373) +SafeCastLibTest:testFailFuzzSafeCastTo8(uint256) (runs: 256, μ: 435, ~: 435) +SafeCastLibTest:testFailFuzzSafeCastTo96(uint256) (runs: 256, μ: 437, ~: 437) +SafeCastLibTest:testFailSafeCastTo128() (gas: 358) +SafeCastLibTest:testFailSafeCastTo160() (gas: 314) +SafeCastLibTest:testFailSafeCastTo192() (gas: 338) +SafeCastLibTest:testFailSafeCastTo224() (gas: 314) +SafeCastLibTest:testFailSafeCastTo248() (gas: 337) +SafeCastLibTest:testFailSafeCastTo32() (gas: 313) +SafeCastLibTest:testFailSafeCastTo64() (gas: 358) +SafeCastLibTest:testFailSafeCastTo8() (gas: 333) +SafeCastLibTest:testFailSafeCastTo96() (gas: 359) +SafeCastLibTest:testFuzzSafeCastTo128(uint256) (runs: 256, μ: 2736, ~: 2736) +SafeCastLibTest:testFuzzSafeCastTo160(uint256) (runs: 256, μ: 2736, ~: 2736) +SafeCastLibTest:testFuzzSafeCastTo192(uint256) (runs: 256, μ: 2714, ~: 2714) +SafeCastLibTest:testFuzzSafeCastTo224(uint256) (runs: 256, μ: 2713, ~: 2713) +SafeCastLibTest:testFuzzSafeCastTo248(uint256) (runs: 256, μ: 2713, ~: 2713) +SafeCastLibTest:testFuzzSafeCastTo32(uint256) (runs: 256, μ: 2736, ~: 2736) +SafeCastLibTest:testFuzzSafeCastTo64(uint256) (runs: 256, μ: 2735, ~: 2735) +SafeCastLibTest:testFuzzSafeCastTo8(uint256) (runs: 256, μ: 2714, ~: 2714) +SafeCastLibTest:testFuzzSafeCastTo96(uint256) (runs: 256, μ: 2714, ~: 2714) +SafeCastLibTest:testSafeCastTo128() (gas: 468) +SafeCastLibTest:testSafeCastTo160() (gas: 466) +SafeCastLibTest:testSafeCastTo192() (gas: 468) +SafeCastLibTest:testSafeCastTo224() (gas: 467) +SafeCastLibTest:testSafeCastTo248() (gas: 446) +SafeCastLibTest:testSafeCastTo32() (gas: 490) +SafeCastLibTest:testSafeCastTo64() (gas: 445) +SafeCastLibTest:testSafeCastTo8() (gas: 465) +SafeCastLibTest:testSafeCastTo96() (gas: 445) +SafeTransferLibTest:testApproveWithMissingReturn() (gas: 30745) +SafeTransferLibTest:testApproveWithNonContract() (gas: 3025) +SafeTransferLibTest:testApproveWithReturnsTooMuch() (gas: 31101) +SafeTransferLibTest:testApproveWithStandardERC20() (gas: 30832) +SafeTransferLibTest:testFailApproveWithReturnsFalse() (gas: 5600) +SafeTransferLibTest:testFailApproveWithReturnsTooLittle() (gas: 5542) +SafeTransferLibTest:testFailApproveWithReverting() (gas: 5565) +SafeTransferLibTest:testFailFuzzApproveWithGarbage(address,uint256,bytes,bytes) (runs: 256, μ: 85010, ~: 77942) +SafeTransferLibTest:testFailFuzzApproveWithReturnsFalse(address,uint256,bytes) (runs: 256, μ: 6449, ~: 6444) +SafeTransferLibTest:testFailFuzzApproveWithReturnsTooLittle(address,uint256,bytes) (runs: 256, μ: 6413, ~: 6408) +SafeTransferLibTest:testFailFuzzApproveWithReturnsTwo(address,uint256,bytes) (runs: 256, μ: 6444, ~: 6439) +SafeTransferLibTest:testFailFuzzApproveWithReverting(address,uint256,bytes) (runs: 256, μ: 6349, ~: 6344) +SafeTransferLibTest:testFailFuzzTransferETHToContractWithoutFallback(uint256,bytes) (runs: 256, μ: 7728, ~: 8025) +SafeTransferLibTest:testFailFuzzTransferFromWithGarbage(address,address,uint256,bytes,bytes) (runs: 256, μ: 119972, ~: 117291) +SafeTransferLibTest:testFailFuzzTransferFromWithReturnsFalse(address,address,uint256,bytes) (runs: 256, μ: 14560, ~: 14554) +SafeTransferLibTest:testFailFuzzTransferFromWithReturnsTooLittle(address,address,uint256,bytes) (runs: 256, μ: 14461, ~: 14455) +SafeTransferLibTest:testFailFuzzTransferFromWithReturnsTwo(address,address,uint256,bytes) (runs: 256, μ: 14551, ~: 14545) +SafeTransferLibTest:testFailFuzzTransferFromWithReverting(address,address,uint256,bytes) (runs: 256, μ: 10689, ~: 10683) +SafeTransferLibTest:testFailFuzzTransferWithGarbage(address,uint256,bytes,bytes) (runs: 256, μ: 90778, ~: 83935) +SafeTransferLibTest:testFailFuzzTransferWithReturnsFalse(address,uint256,bytes) (runs: 256, μ: 9370, ~: 9365) +SafeTransferLibTest:testFailFuzzTransferWithReturnsTooLittle(address,uint256,bytes) (runs: 256, μ: 9314, ~: 9309) +SafeTransferLibTest:testFailFuzzTransferWithReturnsTwo(address,uint256,bytes) (runs: 256, μ: 9365, ~: 9360) +SafeTransferLibTest:testFailFuzzTransferWithReverting(address,uint256,bytes) (runs: 256, μ: 9293, ~: 9288) +SafeTransferLibTest:testFailTransferETHToContractWithoutFallback() (gas: 7261) +SafeTransferLibTest:testFailTransferFromWithReturnsFalse() (gas: 13612) +SafeTransferLibTest:testFailTransferFromWithReturnsTooLittle() (gas: 13515) +SafeTransferLibTest:testFailTransferFromWithReverting() (gas: 9764) +SafeTransferLibTest:testFailTransferWithReturnsFalse() (gas: 8545) +SafeTransferLibTest:testFailTransferWithReturnsTooLittle() (gas: 8463) +SafeTransferLibTest:testFailTransferWithReverting() (gas: 8485) +SafeTransferLibTest:testFuzzApproveWithGarbage(address,uint256,bytes,bytes) (runs: 256, μ: 2949, ~: 2179) +SafeTransferLibTest:testFuzzApproveWithMissingReturn(address,uint256,bytes) (runs: 256, μ: 30826, ~: 31598) +SafeTransferLibTest:testFuzzApproveWithNonContract(address,address,uint256,bytes) (runs: 256, μ: 4145, ~: 4171) +SafeTransferLibTest:testFuzzApproveWithReturnsTooMuch(address,uint256,bytes) (runs: 256, μ: 31181, ~: 31953) +SafeTransferLibTest:testFuzzApproveWithStandardERC20(address,uint256,bytes) (runs: 256, μ: 30935, ~: 31707) +SafeTransferLibTest:testFuzzTransferETH(address,uint256,bytes) (runs: 256, μ: 36207, ~: 37994) +SafeTransferLibTest:testFuzzTransferFromWithGarbage(address,address,uint256,bytes,bytes) (runs: 256, μ: 3391, ~: 2309) +SafeTransferLibTest:testFuzzTransferFromWithMissingReturn(address,address,uint256,bytes) (runs: 256, μ: 48957, ~: 49539) +SafeTransferLibTest:testFuzzTransferFromWithNonContract(address,address,address,uint256,bytes) (runs: 256, μ: 4190, ~: 4229) +SafeTransferLibTest:testFuzzTransferFromWithReturnsTooMuch(address,address,uint256,bytes) (runs: 256, μ: 49617, ~: 50195) +SafeTransferLibTest:testFuzzTransferFromWithStandardERC20(address,address,uint256,bytes) (runs: 256, μ: 47453, ~: 48047) +SafeTransferLibTest:testFuzzTransferWithGarbage(address,uint256,bytes,bytes) (runs: 256, μ: 3037, ~: 2200) +SafeTransferLibTest:testFuzzTransferWithMissingReturn(address,uint256,bytes) (runs: 256, μ: 36571, ~: 37583) +SafeTransferLibTest:testFuzzTransferWithNonContract(address,address,uint256,bytes) (runs: 256, μ: 4144, ~: 4170) +SafeTransferLibTest:testFuzzTransferWithReturnsTooMuch(address,uint256,bytes) (runs: 256, μ: 36907, ~: 37919) +SafeTransferLibTest:testFuzzTransferWithStandardERC20(address,uint256,bytes) (runs: 256, μ: 36538, ~: 37550) +SafeTransferLibTest:testTransferETH() (gas: 34632) +SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 49194) +SafeTransferLibTest:testTransferFromWithNonContract() (gas: 2995) +SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 49816) +SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 47612) +SafeTransferLibTest:testTransferWithMissingReturn() (gas: 36663) +SafeTransferLibTest:testTransferWithNonContract() (gas: 3046) +SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 37064) +SafeTransferLibTest:testTransferWithStandardERC20() (gas: 36738) +TransientReentrancyGuardTest:testFailUnprotectedCall() (gas: 44078) +TransientReentrancyGuardTest:testNoReentrancy() (gas: 5622) +TransientReentrancyGuardTest:testProtectedCall() (gas: 28767) +WETHInvariants:invariantTotalSupplyEqualsBalance() (runs: 256, calls: 3840, reverts: 1827) +WETHTest:testDeposit() (gas: 63223) +WETHTest:testFallbackDeposit() (gas: 63531) +WETHTest:testFuzzDeposit(uint256) (runs: 256, μ: 62708, ~: 65615) +WETHTest:testFuzzFallbackDeposit(uint256) (runs: 256, μ: 62963, ~: 65870) +WETHTest:testFuzzWithdraw(uint256,uint256) (runs: 256, μ: 75388, ~: 78099) +WETHTest:testPartialWithdraw() (gas: 73256) +WETHTest:testWithdraw() (gas: 54352) \ No newline at end of file diff --git a/src/test/TransientReentrancyGuard.t.sol b/src/test/TransientReentrancyGuard.t.sol new file mode 100644 index 00000000..cacc1260 --- /dev/null +++ b/src/test/TransientReentrancyGuard.t.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {DSTestPlus} from "./utils/DSTestPlus.sol"; + +import {TransientReentrancyGuard} from "../utils/TransientReentrancyGuard.sol"; + +contract RiskyContract is TransientReentrancyGuard { + uint256 public enterTimes; + + function unprotectedCall() public { + enterTimes++; + + if (enterTimes > 1) return; + + this.protectedCall(); + } + + function protectedCall() public nonReentrant { + enterTimes++; + + if (enterTimes > 1) return; + + this.protectedCall(); + } + + function overprotectedCall() public nonReentrant {} +} + +contract TransientReentrancyGuardTest is DSTestPlus { + RiskyContract riskyContract; + + function setUp() public { + riskyContract = new RiskyContract(); + } + + function testFailUnprotectedCall() public { + riskyContract.unprotectedCall(); + + assertEq(riskyContract.enterTimes(), 1); + } + + function testProtectedCall() public { + try riskyContract.protectedCall() { + fail("Reentrancy Guard Failed To Stop Attacker"); + } catch {} + } + + function testNoReentrancy() public { + riskyContract.overprotectedCall(); + } +} diff --git a/src/utils/TransientReentrancyGuard.sol b/src/utils/TransientReentrancyGuard.sol new file mode 100644 index 00000000..f25766aa --- /dev/null +++ b/src/utils/TransientReentrancyGuard.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +/// @notice Gas optimized reentrancy protection for smart contracts. Leverages Cancun transient storage. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/TransientReentrancyGuard.sol) +/// @author Modified from Soledge (https://github.com/Vectorized/soledge/blob/main/src/utils/ReentrancyGuard.sol) +abstract contract TransientReentrancyGuard { + /// Warning: Be careful to avoid collisions with this hand picked slot! + uint256 private constant REENTRANCY_GUARD_SLOT = 0x1FACE81BADDEADBEEF; + + + modifier nonReentrant() virtual { + bool noReentrancy; + + /// @solidity memory-safe-assembly + assembly { + noReentrancy := iszero(tload(REENTRANCY_GUARD_SLOT)) + + // Any non-zero value would work, but + // ADDRESS is cheap and certainly not 0. + // Wastes a bit of gas doing this before + // require in the revert path, but we're + // only optimizing for the happy path here. + tstore(REENTRANCY_GUARD_SLOT, address()) + } + + require(noReentrancy, "REENTRANCY"); + + _; + + /// @solidity memory-safe-assembly + assembly { + // Need to set back to zero, as transient + // storage is only cleared at the end of the + // tx, not the end of the outermost call frame. + tstore(REENTRANCY_GUARD_SLOT, 0) + } + } +} From eaa7041378f9a6c12f943de08a6c41b31a9870fc Mon Sep 17 00:00:00 2001 From: t11s Date: Tue, 9 Jul 2024 09:54:41 -0700 Subject: [PATCH 44/44] =?UTF-8?q?=F0=9F=90=9B=20Mask=20address=20args=20in?= =?UTF-8?q?=20STL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/SafeTransferLib.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/utils/SafeTransferLib.sol b/src/utils/SafeTransferLib.sol index 849bea2f..99f7461f 100644 --- a/src/utils/SafeTransferLib.sol +++ b/src/utils/SafeTransferLib.sol @@ -40,9 +40,9 @@ library SafeTransferLib { // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000) - mstore(4, from) // Append the "from" argument. - mstore(36, to) // Append the "to" argument. - mstore(68, amount) // Append the "amount" argument. + mstore(4, and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. + mstore(36, and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. + mstore(68, amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either @@ -74,8 +74,8 @@ library SafeTransferLib { // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) - mstore(4, to) // Append the "to" argument. - mstore(36, amount) // Append the "amount" argument. + mstore(4, and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. + mstore(36, amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either